How to parse a string for having line breaking - javascript

I would like to have a function which takes 3 arguments:
sentence (string),
maxCharLen=20 (number),
separator (string)
and transform the sentence based on the parameters.
Example
var sentence = "JavaScript is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions."
var newSentence = breakSentence(sentence, maxCharLen=20, separator="<br>");
newSentence // JavaScript is a prototype-based <br> scripting language that is dynamic, <br> weakly typed and has first-class functions.
P.S:
This is what I have tried:
var breakSentence = function (sentence, maxCharLen, separator)
{
sentence = sentence || "javascript is a language" ;
maxCharLen = 10 || maxCharLen; // max numb of chars for line
separator = "<br>" || separator;
var offset;
var nbBreak = sentence.length // maxCharLen;
var newSentence = "";
for (var c = 0; c < nbBreak; c += 1)
{
offset = c * maxCharLen;
newSentence += sentence.substring(offset, offset + maxCharLen) + separator;
}
return newSentence;
}
It works in this way:
breakSentence() // "javascript<br> is a lang<br>uage<br>"
it should be:
breakSentence() // "javascript<br>is a <br>language"

Here's a solution: http://snippets.dzone.com/posts/show/869
//+ Jonas Raoni Soares Silva
//# http://jsfromhell.com/string/wordwrap [v1.0]
String.prototype.wordWrap = function(m, b, c){
var i, j, l, s, r;
if(m < 1)
return this;
for(i = -1, l = (r = this.split("\n")).length; ++i < l; r[i] += s)
for(s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s = s.slice(j)).length ? b : ""))
j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m : j.input.length - j[0].length
|| c == 1 && m || j.input.length + (j = s.slice(m).match(/^\S*/)).input.length;
return r.join("\n");
};
usage:
var sentence = "JavaScript is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions."
sentence.wordWrap(20, "<br>",true)
// Output "JavaScript is a <br>prototype-based <br>scripting language <br>that is dynamic, <br>weakly typed and has<br> first-class <br>functions."

I would try it like that (not tested):
var breakSentence = function (sentence, maxCharLen, separator)
{
var result = "";
var index = 0;
while (sentence.length - index > maxCharLen)
{
var spaceIndex = sentence.substring(index, index + maxCharLen).lastIndexOf(' ');
if (spaceIndex < 0) //no spaces
{
alert('Don\'t know what do do with substring with one long word');
spaceIndex = maxCharLen; //assume you want to break anyway to avoid infinite loop
}
result += sentence.substring(index, index + spaceIndex + 1) + separator;
index += spaceIndex + 1;
}
return result;
}
Should break after spaces only now...

Here is my attempt to get it. It has two things you should notice:
it first removes all the separator instances (so the reordering is completely new)
it doesn't break words longer then maxCharLen characters.
It worked in node 0.6.10
var breakSentence = function (sentence, maxCharLen, separator) {
var words = [] // array of words
, i // iterator
, len // loop
, current = '' // current line
, lines = [] // lines split
;
sentence = sentence || "javascript is a language";
maxCharLen = 10 || maxCharLen;
separator = separator || "<br>";
sentence = sentence.replace(separator, '');
if (sentence.length < maxCharLen) return [sentence]; // no need to work if we're already within limits
words = sentence.split(' ');
for (i = 0, len = words.length; i < len; i += 1) {
// lets see how we add the next word. if the current line is blank, just add it and move on.
if (current == '') {
current += words[i];
// if it's not like that, we need to see if the next word fits the current line
} else if (current.length + words[i].length <= maxCharLen) { // if the equal part takes the space into consideration
current += ' ' + words[i];
// if the next word doesn't fit, start on the next line.
} else {
lines.push(current);
current = words[i];
// have to check if this is the last word
if (i === len -1) {
lines.push(current);
}
}
}
// now assemble the result and return it.
sentence = '';
for (i = 0, len = lines.length; i < len; i += 1) {
sentence += lines[i];
// add separator if not the last line
if (i < len -1) {
sentence += separator;
}
}
return sentence;
}

Related

Remove consecutive characters from string until it doesn't have any consecutive characters

If you see two consecutive characters that are the same, you pop them from left to right, until you cannot pop any more characters. Return the resulting string.
let str = "abba"
"abba" - pop the two b's -> "aa"
"aa" - pop the two a's -> ""
return ""
Here's what i have tried so far:
function match(str){
for (let i = 0; i< str.length; i++){
if (str[i] === str[i+1]){
return str.replace(str[i], "");
}
}
};
match('abba');
But it replaces one character only.The problem is if any two consecutive characters matches it needs to remove both of those and console (Like 'abba' to 'aa'). Then it needs to go over the updated string to do the same thing again (Like 'aa' to '')and console until the return string can't be changed anymore.
Here's another solution i found:
function removeAdjacentDuplicates(str) {
let newStr = '';
for (let i = 0; i < str.length; i++) {
if (str[i] !== str[i + 1])
if (str[i - 1] !== str[i])
newStr += str[i];
}
return newStr;
};
removeAdjacentDuplicates('abba');
But this iterates one time only. I need this to go on until there's no more consecutive characters. Also It would be great if good time complexity is maintained.
You can use a while loop to continuously loop until the result is equal to the previous result.
function removeAdjacentDuplicates(str) {
let newStr = '';
for (let i = 0; i < str.length; i++) {
if (str[i] !== str[i + 1])
if (str[i - 1] !== str[i])
newStr += str[i];
}
return newStr;
};
let before = 'abba';
let result = removeAdjacentDuplicates(before);
while(result != before){
before = result;
result = removeAdjacentDuplicates(before);
}
console.log(result);
If you want to add a limit to the number of pops, you can store the maximum pops in a variable and the number of pops in another (incremented in the loop), then add an expression to the while loop that instructs it not to execute when the number of pops is no longer smaller than the maximum number of pops permitted.
E.g:
function removeAdjacentDuplicates(str) {
let newStr = '';
for (let i = 0; i < str.length; i++) {
if (str[i] !== str[i + 1])
if (str[i - 1] !== str[i])
newStr += str[i];
}
return newStr;
};
let before = 'cabbac';
let result = removeAdjacentDuplicates(before);
const maxPop = 2;
var pops = 1; //It's 1 because we already removed the duplicates once on line 11
while (result != before && pops < maxPop) {
before = result;
result = removeAdjacentDuplicates(before);
pops++;
}
console.log(result);
You can use a regular expression to match consecutive characters and keep replacing until the string is unchanged.
function f(s) {
while (s != (s = s.replace(/(.)\1+/g, '')));
return s;
}
console.log(f("abba"))

Counting the occurrence of chars in a javascript string

I have written down code to calculate the count of each of the character in a string.
It seems to be working correctly for some of the words where as for some it fails.
It fails for the last character, as I see the length of the string becomes smaller than the iteration count (but for some of the words)
var str1 = "america"
function noofchars(str1) {
for (var m = 0; m < str1.length + 1; m++) {
var countno = 1;
if (m != 0) {
str1 = str1.slice(1)
}
str2 = str1.substr(0, 1)
for (var i = 0; i < str1.length; i++) {
if (str2 === str1.charAt(i + 1)) {
countno += 1
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
}
}
console.log(str1.charAt(0) + "=" + countno)
}
}
var findnoofchar = noofchars(str1)
It passes for london, philadelphia, sears, happy
But fails for america, chicago etc
london = l=1, o=2, n=2, d=1
It'd be easier to use an object. First reduce into character counts, then iterate through the key/value pairs and console.log:
function noofchars(str1) {
let r = [...str1].reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {});
Object.entries(r).forEach(([k, v]) => console.log(`${k}=${v}`));
}
noofchars("america");
ES5 syntax:
function noofchars(str1) {
var r = str1.split("").reduce(function(a, c) {
a[c] = (a[c] || 0) + 1;
return a;
}, {});
Object.keys(r).forEach(function(k) {
console.log(k + "=" + r[k]);
});
}
noofchars("america");
It's easier to understand what reduce is doing in the above snippet.
First, we take a function with two parameters a and c. These can be called anything, I just use a and c for the accumulator and the current item.
Now, the second line:
a[c] = (a[c] || 0) + 1;
This is kind hard, so let's break it down. First let's look at what's in the parentheses:
a[c] || 0
This checks if a has a key/value pair with the key c (as in, the value of c, not the key literally being c). If that doesn't exist, it returns 0. So if a[c] exists, save it as the value of the expression, otherwise use 0.
Now, we add 1, to increment the value.
Finally, we assign the result to a[c]. So if a contained c, the value of a[c] would be incremented. If a didn't contain c, the value of a[c] would be 1.
Then, we return a to be used in the next iteration of reduce.
In the next line:
}, {});
We assign a default value for a. If we didn't do this, the first time reduce ran, a would be "a", and c would be "m" (the first two characters of america). This way, a is {} (an empty object), and c is "a". If we didn't have this second argument, our function wouldn't work.
In this line:
Object.keys(r).forEach(function(k) {...});
We're getting an array of all the keys in r, and looping through them with forEach, with k being the key.
Then, we're logging k (the key), then an equals sign =, then the value of r[k].
You can split the string by each character and then count the number of occurrence of each character by reduce function as below
function noofchars(str1) {
const chArray = str1.split('');
return chArray.reduce(function(acc, ch) {
if (acc[ch]) {
acc[ch]++;
} else {
acc[ch] = 1;
}
return acc;
}, {});
}
var str1 = "america";
var findnoofchar = noofchars(str1);
console.log(findnoofchar);
In your solution you are mutating str1 in this line
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
which actually changes the length of the string and also checking str1.length in the first loop. In you case you can take the length in the first place. Working version of your code snippet is here
var str1 = "america"
function noofchars(str1) {
const len = str1.length;
for (var m = 0; m < len; m++) {
var countno = 1;
if (m !== 0) {
str1 = str1.slice(1)
}
if (str1.charAt(0) === ' ') {
break;
}
str2 = str1.substr(0, 1)
for (var i = 0; i < str1.length; i++) {
if (str2 === str1.charAt(i + 1)) {
countno += 1
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
}
}
console.log(str1.charAt(0) + "=" + countno)
}
}
var findnoofchar = noofchars(str1)
Not really knowing what you are trying to accomplish with your code, one solution is to utilize the charAt and Set functions. CharAt is a more direct way to iterate over the string and the Set function eliminates duplicate characters from the set automatically.
var str1 = "america";
function noofchars(str1) {
var charList = new Set();
for (var m = 0; m < str1.length; m++) {
var charX = str1.charAt(m).substr(0, 1);
var countno = 1;
for (var i = 0; i < str1.length; i++) {
if (str1.slice(0, i + 1) == charX) {
countno++;
}
charList.add(charX + "=" + countno);
}
}
// you may need to expand set on Chrome console
console.log(charList);
// a hack to display more easily display on your screen
var listOnScreen = Array.from(charList);
document.getElementById('displaySet').innerHTML=listOnScreen;
}
noofchars(str1);
<div id="displaySet"></div>

Manually remove whitespace in String - JavaScript

I have attempted to make an algorithm that will do the same thing as this function: var string= string.split(' ').join('');
So if I have the following String: Hello how are you it becomes Hellohowareyou
I don't want to use .replace or regex or .split
However, the algorithm doesn't seem to make any changes to the String:
var x = prompt("Enter String");
for (var i=0; i<=x.length;i++) {
if (x[i] == " ") {
x[i] = "";
}
}
alert(x);
Iterate over the string copying characters, skipping spaces. Your code doesn't work because strings are immutable, so you cannot change characters within the string by doing x[i] = 'c'.
See Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?
var string = 'Hello How are you';
var noSpaces = '';
for (var i = 0; i < string.length; i++) {
if (string.charAt(i) != ' ' ) {
noSpaces += string.charAt(i);
}
}
alert(noSpaces);
Your code is not working because, probably for strings, similar to a getter, there is no setter for indexed approach(x[0] = "w"). You cannot consider a string as an array. Its a special form of object (immutable object) that can be accessed with index, but strictly there is no setter in this approach.
You can fix your code by changing like below,
var x = prompt("Enter sum or 'e' to Exit");
var modified = "";
for (var i=0; i<x.length;i++) {
if (x[i] != " ") {
modified += x[i];
}
}
alert(modified);
And you can do this in other better ways like below by using regex,
var x = prompt("Enter sum or 'e' to Exit");
x = x.replace(/\s/g,"");
In your code you just compare the value and try to replace with same variable but it's not possible to replace same with variable, just stored your value with new variable some thing like below
var x = prompt("Enter sum or 'e' to Exit");
var v='';
for (var i=0; i<x.length;i++) {
if (x[i] != " ") {
v +=x[i];
}
}
alert(v);
Here is the link https://jsfiddle.net/rqL3cvog/
Another approach, which updates the variable x and does not use another variable is to use a reverse for loop and use slice to take the string before and after i:-
var x = prompt("Enter String");
for (var i = x.length; i--;) {
if (x[i] == " ") {
x = x.slice(0, i) + x.slice(i + 1, x.length);
}
}
alert(x);
Or, a reverse for loop with substr :-
var x = prompt("Enter String");
for (var i = x.length; i--;) {
if (x[i] == " ") {
x = x.substr(0, i) + x.substr(i + 1);
}
}
alert(x);
Hie ,
Please check below code. Its lengthy. But others can help to make it short. Check output
var x = prompt("Hello how are you");
y = ''
flag = false
for (var i=0; i<x.length;i++) {
if (x[i] == " ") {
flag= true
}
else {
if (flag == true) {
y += ' '
y += x[i]
flag = false
}
else {
y += x[i]
}
}
}
alert(y)
Output is : "Hello how are you"
Code just sets a flag when you get a space in x[i] & when you get next character its just add single space instead of whitespace & adds next character to output string & again sets flag to false.

Is there a way I can change the contents of a variable in Camel Case to space separated words?

I have a variable which contains this:
var a = "hotelRoomNumber";
Is there a way I can create a new variable from this that contains: "Hotel Room Number" ? I need to do a split on the uppercase character but I've not seen this done anywhere before.
Well, you could use a regex, but it's simpler just to build a new string:
var a = "hotelRoomNumber";
var b = '';
if (a.length > 0) {
b += a[0].toUpperCase();
for (var i = 1; i != a.length; ++i) {
b += a[i] === a[i].toUpperCase() ? ' ' + a[i] : a[i];
}
}
// Now b === "Hotel Room Number"
var str = "mySampleString";
str = str.replace(/([A-Z])/g, ' $1').replace(/^./, function(str){ return str.toUpperCase(); });
http://jsfiddle.net/PrashantJ/zX8RL/1/
I have made a function here:
http://jsfiddle.net/wZf6Z/2/
function camelToSpaceSeperated(string)
{
var char, i, spaceSeperated = '';
// iterate through each char
for (i = 0; i < string.length; i++) {
char = string.charAt(i); // current char
if (i > 0 && char === char.toUpperCase()) { // if is uppercase
spaceSeperated += ' ' + char;
} else {
spaceSeperated += char;
}
}
// Make the first char uppercase
spaceSeperated = spaceSeperated.charAt(0).toUpperCase() + spaceSeperated.substr(1);
return spaceSeperated;
}
The general idea is to iterate through each char in the string, check if the current char is already uppercased, if so then prepend a space to it.

how to increment the value of a char in Javascript

How do I increment a string "A" to get "B" in Javascript?
function incrementChar(c)
{
}
You could try
var yourChar = 'A'
var newChar = String.fromCharCode(yourChar.charCodeAt(0) + 1) // 'B'
So, in a function:
function incrementChar(c) {
return String.fromCharCode(c.charCodeAt(0) + 1)
}
Note that this goes in ASCII order, for example 'Z' -> '['. If you want Z to go back to A, try something slightly more complicated:
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
function incrementChar(c) {
var index = alphabet.indexOf(c)
if (index == -1) return -1 // or whatever error value you want
return alphabet[index + 1 % alphabet.length]
}
var incrementString = function(string, count){
var newString = [];
for(var i = 0; i < string.length; i++){
newString[i] = String.fromCharCode(string[i].charCodeAt() + count);
}
newString = newString.join('');
console.log(newString);
return newString;
}
this function also can help you if you have a loop to go through

Categories

Resources