I have the following code which sets special to run a function convertSpecial which will replace the apostrophe in array1 with a provided character. In this case, a space. Since the replacing character is a space, it will split that element into two then flatten the array. It will then check to see if any element in special matches any element in array2. This will return false. It will then replace the apostrophe with no character at all and recheck against array2.
The idea behind convertSpecial and the variable special is that it should be non-destructive to array1, but this isn't happening as you can see:
var array1 = ["o'hara"];
var array2 = ["ohara"];
var special = '';
function convertSpecial(a,b,c) {
var aCopy = a;
for (let i = 0; i < aCopy.length; i++) {
if (aCopy[i].includes(b)) {
if (c == '') {
aCopy[i] = aCopy[i].replace(b,c);
} else {
aCopy[i] = aCopy[i].replace(b,c).split(' ');
aCopy = aCopy.flat();
}
}
}
return aCopy;
}
console.log('array1 1 = '+array1); // returns array1 1 = o'hara as expected
special = convertSpecial(array1,"'"," ");
console.log('array1 2 = '+array1); // returns array1 2 = o,hara THIS SHOULD NOT HAVE BEEN MODIFIED
console.log('special 1 = '+special); //returns special 2 = o,hara as expected
if (array2.some(v => special.includes(v)) == true) {
console.log('array1 3 = '+array1); // ignored as expected
array1 = specialDECln;
} else {
console.log('array1 4 = '+array1); //returns array1 4 = o,hara THIS SHOULD NOT HAVE BEEN MODIFIED
special = convertSpecial(array1,"'","");
console.log('array1 5 = '+array1); //returns array1 5 = o,hara THIS SHOULD NOT HAVE BEEN MODIFIED
console.log('special 2= '+special); //returns special 2 = o,hara should be ohara
if (array2.some(v => special.includes(v)) == true) {
array1 = special;
}
}
console.log(array2 == special); //returns false, should be true because expected ohara = ohara
Everything works as it should, EXCEPT array1 is being modified when it shouldn't be at all. Since it gets modified, special gets set to an incorrect value.
What am I doing wrong and how can I fix it?
You need to clone that array in order to avoid mutation. There are a lot of ways for doing that, an alternative is using the Spread-syntax as follow:
let result = [...a]; // This creates a new array with the index-values from array a.
var array1 = ["o'hara"];
var special = ''
console.log("array1 = " + array1); // returns array1 = o'hara as expected
function convertSpecial(a, b, c) { // a = array, b = character to replace, c = character to replace with
let result = [...a];
for (let i = 0; i < result.length; i++) {
if (result[i].includes(b)) {
if (c == '') {
result[i] = result[i].replace(b, c);
} else {
result[i] = result[i].replace(b, c).split(' ');
result = result.flat();
}
}
}
return result;
}
special = convertSpecial(array1, "'", " ");
console.log("array1 = " + array1); // returns array1 = o, hara but it should be o'hara
console.log("special = " + special); // returns special = o, hara as expected
You need to duplicate the array first:
var array1 = ["o'hara"];
var special = ''
console.log("array1 = " + array1); // returns array1 = o'hara as expected
function convertSpecial(a, b, c) { // a = array, b = character to replace, c = character to replace with
var aCopy = a.slice();
for (let i = 0; i < aCopy.length; i++) {
if (aCopy[i].includes(b)) {
if (c == '') {
aCopy[i] = aCopy[i].replace(b, c);
} else {
aCopy[i] = aCopy[i].replace(b, c).split(' ');
aCopy = aCopy.flat();
}
}
}
return aCopy;
}
special = convertSpecial(array1, "'", " ");
console.log("array1 = " + array1); // returns array1 = o, hara but it should be o'hara
console.log("special = " + special); // returns special = o, hara as expected
I have a string in this format:
var x = "a=1; b=2; c=3; d=4"
and I would like to convert it to an object like this:
var y = {
a: "1",
b: "2",
c: "3",
d: "4"
}
Any ideas how to achieve that?
This works in iE9+
var x = "a=1; b=2; c=3; d=4",
y = {};
x.split(';').map(function (i) {
return i.split('=')
}).forEach(function (j) {
y[j[0].trim()] = j[1]
});
If you are using Node.js v4+
let x = "a=1; b=2; c=3; d=4",
y = {}
x.split(';').map(i => i.split('=')).forEach(j => y[j[0].trim()] = j[1])
You could try this (not bullet proof, refer to comments):
var json, str;
str = 'a=1; b=2; c=3; d=4';
str = str.replace(/\s*;\s*/g, ',');
str = str.replace(/([^,]+)=([^,]+)/g, '"$1":"$2"');
str = '{' + str + '}';
json = JSON.parse(str);
document.write(
'<pre>' + JSON.stringify(json) + '</pre>'
);
here is what i did and it seems to work fine:
var y = x.split(";");
var obj = {};
for(var i = 0; i < y.length ; i++){
var k = y[i].split("=");
var r = k[0].replace(" ", "");
obj[r] = k[1];
}
console.log(obj);
Can someone help me to do these example?
var a = ["17","18"];
var b = ["1","1","1"];
I need an output below:
var c = [17:111,18:111]
var a = ["17","18"];
var b = ["1","1","1"];
var i=0;
var ConcateC="";
for(i=0;i< b.length;i++)
{
ConcateC +=b[i];
}
var c=[];
for(i=0;i< a.length;i++)
{
c[i]=a[i] + ":" + ConcateC;
alert(c[i]);
}
You can join the values of b together, then use map to create a new array from the indices of a:
var a = ["17","18"];
var b = ["1","1","1"];
var bValue = b.join("");
var c = a.map(function(currentValue) {
return currentValue + ":" + bValue;
});
console.log(c); // ["17:111","18:111"]
As the title says, I've got a string and I want to split into segments of n characters.
For example:
var str = 'abcdefghijkl';
after some magic with n=3, it will become
var arr = ['abc','def','ghi','jkl'];
Is there a way to do this?
var str = 'abcdefghijkl';
console.log(str.match(/.{1,3}/g));
Note: Use {1,3} instead of just {3} to include the remainder for string lengths that aren't a multiple of 3, e.g:
console.log("abcd".match(/.{1,3}/g)); // ["abc", "d"]
A couple more subtleties:
If your string may contain newlines (which you want to count as a character rather than splitting the string), then the . won't capture those. Use /[\s\S]{1,3}/ instead. (Thanks #Mike).
If your string is empty, then match() will return null when you may be expecting an empty array. Protect against this by appending || [].
So you may end up with:
var str = 'abcdef \t\r\nghijkl';
var parts = str.match(/[\s\S]{1,3}/g) || [];
console.log(parts);
console.log(''.match(/[\s\S]{1,3}/g) || []);
If you didn't want to use a regular expression...
var chunks = [];
for (var i = 0, charsLength = str.length; i < charsLength; i += 3) {
chunks.push(str.substring(i, i + 3));
}
jsFiddle.
...otherwise the regex solution is pretty good :)
str.match(/.{3}/g); // => ['abc', 'def', 'ghi', 'jkl']
Building on the previous answers to this question; the following function will split a string (str) n-number (size) of characters.
function chunk(str, size) {
return str.match(new RegExp('.{1,' + size + '}', 'g'));
}
Demo
(function() {
function chunk(str, size) {
return str.match(new RegExp('.{1,' + size + '}', 'g'));
}
var str = 'HELLO WORLD';
println('Simple binary representation:');
println(chunk(textToBin(str), 8).join('\n'));
println('\nNow for something crazy:');
println(chunk(textToHex(str, 4), 8).map(function(h) { return '0x' + h }).join(' '));
// Utiliy functions, you can ignore these.
function textToBin(text) { return textToBase(text, 2, 8); }
function textToHex(t, w) { return pad(textToBase(t,16,2), roundUp(t.length, w)*2, '00'); }
function pad(val, len, chr) { return (repeat(chr, len) + val).slice(-len); }
function print(text) { document.getElementById('out').innerHTML += (text || ''); }
function println(text) { print((text || '') + '\n'); }
function repeat(chr, n) { return new Array(n + 1).join(chr); }
function textToBase(text, radix, n) {
return text.split('').reduce(function(result, chr) {
return result + pad(chr.charCodeAt(0).toString(radix), n, '0');
}, '');
}
function roundUp(numToRound, multiple) {
if (multiple === 0) return numToRound;
var remainder = numToRound % multiple;
return remainder === 0 ? numToRound : numToRound + multiple - remainder;
}
}());
#out {
white-space: pre;
font-size: 0.8em;
}
<div id="out"></div>
If you really need to stick to .split and/or .raplace, then use /(?<=^(?:.{3})+)(?!$)/g
For .split:
var arr = str.split( /(?<=^(?:.{3})+)(?!$)/ )
// [ 'abc', 'def', 'ghi', 'jkl' ]
For .replace:
var replaced = str.replace( /(?<=^(?:.{3})+)(?!$)/g, ' || ' )
// 'abc || def || ghi || jkl'
/(?!$)/ is to not stop at end of the string. Without it's:
var arr = str.split( /(?<=^(?:.{3})+)/ )
// [ 'abc', 'def', 'ghi', 'jkl' ] // is fine
var replaced = str.replace( /(?<=^(.{3})+)/g, ' || ')
// 'abc || def || ghi || jkl || ' // not fine
Ignoring group /(?:...)/ is to prevent duplicating entries in the array. Without it's:
var arr = str.split( /(?<=^(.{3})+)(?!$)/ )
// [ 'abc', 'abc', 'def', 'abc', 'ghi', 'abc', 'jkl' ] // not fine
var replaced = str.replace( /(?<=^(.{3})+)(?!$)/g, ' || ' )
// 'abc || def || ghi || jkl' // is fine
My solution (ES6 syntax):
const source = "8d7f66a9273fc766cd66d1d";
const target = [];
for (
const array = Array.from(source);
array.length;
target.push(array.splice(0,2).join(''), 2));
We could even create a function with this:
function splitStringBySegmentLength(source, segmentLength) {
if (!segmentLength || segmentLength < 1) throw Error('Segment length must be defined and greater than/equal to 1');
const target = [];
for (
const array = Array.from(source);
array.length;
target.push(array.splice(0,segmentLength).join('')));
return target;
}
Then you can call the function easily in a reusable manner:
const source = "8d7f66a9273fc766cd66d1d";
const target = splitStringBySegmentLength(source, 2);
Cheers
const chunkStr = (str, n, acc) => {
if (str.length === 0) {
return acc
} else {
acc.push(str.substring(0, n));
return chunkStr(str.substring(n), n, acc);
}
}
const str = 'abcdefghijkl';
const splittedString = chunkStr(str, 3, []);
Clean solution without REGEX
My favorite answer is gouder hicham's. But I revised it a little so that it makes more sense to me.
let myString = "Able was I ere I saw elba";
let splitString = [];
for (let i = 0; i < myString.length; i = i + 3) {
splitString.push(myString.slice(i, i + 3));
}
console.log(splitString);
Here is a functionalized version of the code.
function stringSplitter(myString, chunkSize) {
let splitString = [];
for (let i = 0; i < myString.length; i = i + chunkSize) {
splitString.push(myString.slice(i, i + chunkSize));
}
return splitString;
}
And the function's use:
let myString = "Able was I ere I saw elba";
let mySplitString = stringSplitter(myString, 3);
console.log(mySplitString);
And it's result:
>(9) ['Abl', 'e w', 'as ', 'I e', 're ', 'I s', 'aw ', 'elb', 'a']
try this simple code and it will work like magic !
let letters = "abcabcabcabcabc";
// we defined our variable or the name whatever
let a = -3;
let finalArray = [];
for (let i = 0; i <= letters.length; i += 3) {
finalArray.push(letters.slice(a, i));
a += 3;
}
// we did the shift method cause the first element in the array will be just a string "" so we removed it
finalArray.shift();
// here the final result
console.log(finalArray);
var str = 'abcdefghijkl';
var res = str.match(/.../g)
console.log(res)
here number of dots determines how many text you want in each word.
function chunk(er){
return er.match(/.{1,75}/g).join('\n');
}
Above function is what I use for Base64 chunking. It will create a line break ever 75 characters.
Here we intersperse a string with another string every n characters:
export const intersperseString = (n: number, intersperseWith: string, str: string): string => {
let ret = str.slice(0,n), remaining = str;
while (remaining) {
let v = remaining.slice(0, n);
remaining = remaining.slice(v.length);
ret += intersperseWith + v;
}
return ret;
};
if we use the above like so:
console.log(splitString(3,'|', 'aagaegeage'));
we get:
aag|aag|aeg|eag|e
and here we do the same, but push to an array:
export const sperseString = (n: number, str: string): Array<string> => {
let ret = [], remaining = str;
while (remaining) {
let v = remaining.slice(0, n);
remaining = remaining.slice(v.length);
ret.push(v);
}
return ret;
};
and then run it:
console.log(sperseString(5, 'foobarbaztruck'));
we get:
[ 'fooba', 'rbazt', 'ruck' ]
if someone knows of a way to simplify the above code, lmk, but it should work fine for strings.
Coming a little later to the discussion but here a variation that's a little faster than the substring + array push one.
// substring + array push + end precalc
var chunks = [];
for (var i = 0, e = 3, charsLength = str.length; i < charsLength; i += 3, e += 3) {
chunks.push(str.substring(i, e));
}
Pre-calculating the end value as part of the for loop is faster than doing the inline math inside substring. I've tested it in both Firefox and Chrome and they both show speedup.
You can try it here
Here's a way to do it without regular expressions or explicit loops, although it's stretching the definition of a one liner a bit:
const input = 'abcdefghijlkm';
// Change `3` to the desired split length.
const output = input.split('').reduce((s, c) => {
let l = s.length-1;
(s[l] && s[l].length < 3) ? s[l] += c : s.push(c);
return s;
}, []);
console.log(output); // output: [ 'abc', 'def', 'ghi', 'jlk', 'm' ]
It works by splitting the string into an array of individual characters, then using Array.reduce to iterate over each character. Normally reduce would return a single value, but in this case the single value happens to be an array, and as we pass over each character we append it to the last item in that array. Once the last item in the array reaches the target length, we append a new array item.
Some clean solution without using regular expressions:
/**
* Create array with maximum chunk length = maxPartSize
* It work safe also for shorter strings than part size
**/
function convertStringToArray(str, maxPartSize){
const chunkArr = [];
let leftStr = str;
do {
chunkArr.push(leftStr.substring(0, maxPartSize));
leftStr = leftStr.substring(maxPartSize, leftStr.length);
} while (leftStr.length > 0);
return chunkArr;
};
Usage example - https://jsfiddle.net/maciejsikora/b6xppj4q/.
I also tried to compare my solution to regexp one which was chosen as right answer. Some test can be found on jsfiddle - https://jsfiddle.net/maciejsikora/2envahrk/. Tests are showing that both methods have similar performance, maybe on first look regexp solution is little bit faster, but judge it Yourself.
var b1 = "";
function myFunction(n) {
if(str.length>=3){
var a = str.substring(0,n);
b1 += a+ "\n"
str = str.substring(n,str.length)
myFunction(n)
}
else{
if(str.length>0){
b1 += str
}
console.log(b1)
}
}
myFunction(4)
function str_split(string, length = 1) {
if (0 >= length)
length = 1;
if (length == 1)
return string.split('');
var string_size = string.length;
var result = [];
for (let i = 0; i < string_size / length; i++)
result[i] = string.substr(i * length, length);
return result;
}
str_split(str, 3)
Benchmark: http://jsben.ch/HkjlU (results differ per browser)
Results (Chrome 104)
I have a large string that comes across the wire using an $.ajax request. I can format the string any way necessary, and currently am using a % as the line delimiter and , as the item delimiter. Considering performance is so essential in my application, does anyone have a quicker way to do the following? Thank You
function convertCSV(s) {
var lines = s.split("%");
var items, sym, arr = [];
for (var x = 0, len = lines.length; x < len; x++) {
items = lines[x].split(",");
sym = {};
sym.time = +items[0];
sym.num1 = +items[1];
sym.num2 = +items[2];
sym.a1 = +items[3];
sym.b1 = +items[4];
sym.c1 = +items[5];
sym.d1 = +items[6];
sym.e1 = +items[7];
sym.f1 = +items[8];
sym.g1 = +items[9];
sym.h1 = +items[10];
sym.l1 = +items[11];
arr[x] = sym;
}
return arr;
}
Perhaps JSON encode what you send over the wire and then JSON decode once you receive it.
A (minor) optimisation:
function convertCSV(s) {
var lines = s.split("%");
var items, arr = [];
while ((items = lines.shift()) && (items = items.split(",")) {
arr.push({
time : +items[0], num1 : +items[1], num2 : +items[2],
a1 : +items[3], b1 : +items[4], c1 : +items[5],
d1 : +items[6], e1 : +items[7], f1 : +items[8],
g1 : +items[9], h1 : +items[10], l1 : +items[11]
});
}
return arr;
}
Could be worth experimenting with Array.shift() and Array.pop()
If you are concerned about speed, you should probably create a simply parser that will parse the string character by character.
Here's a simple example:
DEMO
function convertCSV(s, properties) {
var result = [],
i = 0,
len = s.length,
propIndex = 0,
row = {},
val = '',
c;
for (; i < len; i++) {
switch(c = s[i]) {
case ',':
row[properties[propIndex++]] = val;
val = '';
break;
case '%':
result.push(row);
row[properties[propIndex++]] = val;
propIndex = 0;
row = {};
val = '';
break;
default:
val += c;
}
}
return result;
}
console.log(convertCSV('a,b,c%d,e,f%h,i,j%', ['a', 'b', 'c']));
EDIT:
I ran a few performance tests and it seems that I wasn`t right afterall. Your current method is actually the second fastest, but the quickest way to do this seems to be using regular expressions. I must say that I am quite surprised that the simple parser isin't the fastest solution.
PERFORMANCE TEST
var rx = /(.*?),(.*?),(.*?)%/g,
result = [],
match;
while (match = rx.exec(s)) {
result.push({
a: match[1],
b: match[2],
c: match[3]
});
}
console.log(result);