Merge Two Arrays so that the Values Alternate - javascript

I'm looking for a jQuery method to merge two arrays so that their values alternate:
var array1 = [1,2,3,4,5];
var array2 = ['a', 'b', 'c', 'd', 'e'];
The result I want is:
var arrayCombined = [1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e'];
Please note that I know it is trivial to do this in JS, however I am after a jQuery method that will do this.

You can use the map method:
var array1 = [1, 2, 3, 4, 5];
var array2 = ['a', 'b', 'c', 'd', 'e'];
var arrayCombined = $.map(array1, function(v, i) {
return [v, array2[i]];
});
console.log(arrayCombined);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Demo: http://jsfiddle.net/Guffa/hmUy6/

If you must use jQuery, you can take advantage of their broken $.map implementation.
var result = $.map(array1, function(v, i) {
return [v, array2[i]];
});
jQuery's $.map flattens the returned array, giving you the result you want.
DEMO: http://jsfiddle.net/8rn2w/
Pure JS solution:
var result = array1.reduce(function(arr, v, i) {
return arr.concat(v, array2[i]);
}, []);
DEMO: http://jsfiddle.net/8rn2w/1/

Just another solution using Array.prototype.flat() and Array.prototype.map().
var array1 = [1, 2, 3, 4, 5];
var array2 = ['a', 'b', 'c', 'd', 'e'];
var result = array1.map(
(element, index) => [element, array2[index]]
).flat();
console.log(result);

For those who arrive here by search engine and want a Lodash option:
_.compact(_.flatten(_.zip(array1, array2)))

Try something like this:
function merge(array1, array2) {
if (array1.length == array2.length) {
var c = [];
for (var i = 0; i < array1.length; i++) {
c.push([array1[i], array2[i]]);
}
return c;
}
return null;
}

I came here curious to see if there was a new Array.prototype.<whatever>() that was helpful for this - and flatMap is that... kinda - but I'm going to leave with the simplest, most obvious solution...
(and a few tears that in 10 years no one else used a for loop to build a single array)
Plain, old JavaScript
If you were merging bits of something like stereo channels, or template strings, etc, this is all you need:
// Supports the two most common cases:
// - interleaving left and right audio channels
// - interleaving template string and values
// (right is assumed to be the same length as left, or one shorter)
function interleave(left, right) {
var both = [];
var i;
for (i = 0; i < left.length; i += 1) {
both.push(left[i]);
// because a template string will have one fewer value
// than it will have string parts
if (i < right.length) {
both.push(right[i]);
}
}
return both;
}
// a template string will always have one extra item
var abc = ['a', 'b', 'c', 'd' ];
var one = [1, 2, 3 ];
var both = interleave(abc, one);
console.log(both);
// ['a', 1, 'b', 2, 'c', 3, 'd']
flatMap
As mentioned in a comment, this is probably suitable:
function cleverInterleave() {
return abc.flatMap(function (val, i) {
if (one[i]) {
return [val, one[i]];
}
return [val];
});
}
var abc = ['a', 'b', 'c', 'd' ];
var one = [1, 2, 3 ];
cleverInterleave(abc, one);
// ['a', 1, 'b', 2, 'c', 3, 'd']
However, this seems a little too "clever" and not as intuitive. Also not as efficient... but readability counts far more than efficiency for most code, so... two strikes against.
mo' channels, mo' problems
You could also create a more generic form of this to handle arbitrary numbers of arrays, or zip up arrays of uneven lengths.
However, I'd recommend using a similar pattern, but tuned to the actual number of arrays that you need - such as 3 for RGB, or 4 for RGBA, etc.

Related

Better way to check if an element only exists in one array

I need help with creating a function to return the elements that are only present in one of 3 arrays, for example
let arr1 = ['a', 'b', 'c', 'a', 'b']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a']
In the three arrays above, 'd' and 'f' are found only in one of the arrays (arr2 and arr3), I need to return them.
['d','f']
The arrays can be of different sizes and the returned elements must not be duplicated.
I tried to find better alternatives, but I failed and just went with the brute force approach, looping through each array and checking if the element exists in the other two arrays, but obviously, it's really slow and hard to read.
function elementsInOnlyOneArr(a1, a2, a3) {
let myArr = [];
for(let el of a1){
if(a2.includes(el) == false && a3.includes(el) == false && myArr.includes(el) == false){
myArr.push(el);
}
}
for(let el of a2){
if(a1.includes(el) == false && a3.includes(el) == false && myArr.includes(el) == false){
myArr.push(el);
}
}
for(let el of a3){
if(a2.includes(el) == false && a1.includes(el) == false && myArr.includes(el) == false){
myArr.push(el);
}
}
return myArr;
}
Assuming there are less than 32 arrays, you can do this efficiently with bitmaps. Basically, build an index key -> number where the number has the Nth bit set if the key is in the Nth array. Finally return keys whose numbers only have a single bit set (=are powers of two):
function difference(...arrays) {
let items = {}
for (let [n, a] of arrays.entries())
for (let x of a) {
items[x] = (items[x] ?? 0) | (1 << n)
}
return Object.keys(items).filter(x =>
Number.isInteger(Math.log2(items[x])))
}
let arr1 = ['a', 'b', 'c', 'a', 'b', 'z', 'z', 'z']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a']
console.log(difference(arr1, arr2, arr3))
(As noted in the comments x & (x-1) === 0 would be more idiomatic to check whether x is a power of two. See How does the formula x & (x - 1) works? for explanations.)
Here's a more general approach that doesn't limit the number of arrays and doesn't require keys to be strings:
function difference(...arrays) {
let items = new Map
for (let [n, a] of arrays.entries())
for (let x of a) {
if (!items.has(x))
items.set(x, new Set)
items.get(x).add(n)
}
let result = []
for (let [x, ns] of items)
if (ns.size === 1)
result.push(x)
return result
}
let arr1 = ['a', 'b', 'c', 'a', 'b', 'z', 'z', 'z']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a']
console.log(difference(arr1, arr2, arr3))
EDIT: Misunderstood OP and it's not an intersect, but extracting values that are unique (e.g. NOT the intersection) between the individual arrays, for that this might work:
let arr1 = ['a', 'b', 'c', 'a', 'b'];
let arr2 = ['a', 'd', 'b', 'c'];
let arr3 = ['f', 'c', 'a'];
const thereCanOnlyBeOne = function(...arrs) {
return Array.from(
arrs.reduce((map, arr) => {
new Set(arr).forEach((v) => map.set(v, map.has(v) ? map.get(v)+1 : 1));
return map;
}, new Map())
)
.filter(([value, count]) => count === 1)
.map(([value, count]) => value);
};
console.log(thereCanOnlyBeOne(arr1, arr2, arr3));
I would think #gog's answer is way more sophisticated and probably much faster, but i have a slightly hard time wrapping my head around it (call me stupid, i take it =D, EDIT: had to do some research, read/learn something about bitsets here and here), so here's the breakdown of the slightly convoluted way of doing this with a Map and array methods:
pass all arrays to be analyzed into function, order doesn't matter
Loop (i chose reduce, but any loop structure works) trough all input arrays and their values, counting up occurrences in the Map, at the end the Map will look as follows:
0: {"a" => 4}
1: {"b" => 3}
2: {"c" => 3}
3: {"d" => 1}
4: {"f" => 1}
Once done with that, we convert the Map back into an array via Array.from() creating an array of tuples:
[
["a", 4],
["b", 3],
["c", 3],
["d", 1],
["f", 1],
]
Filter that resulting array of tuples (now in the form of [<value>, <count>] to only be left with values that exactly occurred once, leaving us with:
[
["d", 1],
["f", 1],
]
Map over the filtered array to "dumb" it down into a one-dimensional array again and return the result:
["d", "f"]
WARNING: Internally this code does a ****load of loops, so call it a brute-force loop as well, it just looks "shorter" due to "sexy" ES6 array-syntax-sugar.
A slightly modified version for completeness as the Array.filter() step can be omitted (although it seems to be faster) by iterating the counter-Map once it's finalized and simply deleting Map-entries that do not have value 1.
let arr1 = ['a', 'b', 'c', 'a', 'b'];
let arr2 = ['a', 'd', 'b', 'c'];
let arr3 = ['f', 'c', 'a'];
const thereCanOnlyBeOne = function(...arrs) {
let result;
arrs
.reduce((map, arr) => {
new Set(arr).forEach((v) => map.set(v, map.has(v) ? map.get(v)+1 : 1));
return map;
}, new Map())
// the result of .reduce will be a Map!
.forEach((value, key, map) => { value !== 1 && map.delete(key); result = map; });
return Array.from(result).map(([value, count]) => value);
};
console.log(thereCanOnlyBeOne(arr1, arr2, arr3));
UPDATE: as #Nick Parsons pointed out, the previous version of the code would not output elements that were only present in one array, but multiple times.
This will produce an incorrect output if one array contains the same value multiple times and that element isn't present in any other arrays. eg, if you remove b from arr2, then only arr1 has b in it but no others do, so it should b should be included in the final result.
This can easily be solved by turning the array that is checked into a Set() (thereby reducing the arrays values to "unique" ones).
If anyone (besides me) wonders, here's a benchmark between gog's options and mine, his bitset approach is clearly the fastest, so if you are comparing less than 32 arrays, that's the most performant solution by far: https://jsben.ch/YkKSu
and if anyone prefers an ES6-ified version of gog's bitset implementation (improved by #ralphmerridew suggestion), here you go:
let arr1 = ['a', 'b', 'c', 'a', 'b'];
let arr2 = ['a', 'd', 'b', 'c'];
let arr3 = ['f', 'c', 'a'];
function onlyone(...arrays) {
return Object.entries(
arrays.reduce((map, arr, n) => {
arr.forEach((v) => map[v] = (map[v] ?? 0) | (1 << n));
return map;
}, {})
)
.filter(([value, bitmap]) => (bitmap & (bitmap-1)) == 0)
.map(([value, bitmap]) => value);
};
console.log(onlyone(arr1, arr2, arr3));
updated the benchmark with this as well, interestingly (or unexpectedly) this "slower"-looking ES6 implementation somehow beats gog's for-loop implementation by a tad, tested in chrome and firefox multiple times, as i couldn't believe it myself, thought those syntax-sugar methods slow things down slightly compared to for loops, well...good to know =)
I also tried implementing the bitset approach with BigInt() to eliminate the issue with it only being able to deal with 32 arrays (depending on the Engine with BigInt it should be possible to deal with 1 million to 1 billion arrays), unfortunately that seems to make it the slowest of all solutions (benchmark updated):
let arr1 = ['a', 'b', 'c', 'a', 'b'];
let arr2 = ['a', 'd', 'b', 'c'];
let arr3 = ['f', 'c', 'a'];
function onlyoneBigInt(...arrays) {
return Object.entries(
arrays.reduce((map, arr, n) => {
arr.forEach((v) => map[v] = (map[v] ?? 0n) | (1n << BigInt(n)));
return map;
}, {})
)
.filter(([value, bitmap]) => (bitmap & (bitmap-1n)) == 0)
.map(([value, bitmap]) => value);
};
console.log(onlyoneBigInt(arr1, arr2, arr3));
Maybe someone sees something that can be improved to make this faster?
This is really just Set operations. The method single below finds any entry in a test array that does not appear in the other arrays in the collection. Deliberately implementing this so you can test individual arrays since it's not clear in the question if you need to return the letters, or the arrays.
let arr1 = ['a', 'b', 'c', 'a', 'b']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a']
// The set of arrays
let arrays = [ arr1, arr2, arr3 ]
// Finds any entries in the test array that doesn't appear in the arrays that aren't the test arrays
let singles = (test) => {
// others is the Set of all value in the other arrays
others = arrays.reduce( ( accum, elem ) => {
if (elem != test) { elem.forEach(accum.add, accum) }
return accum
}, new Set())
// find anything in the test array that the others do not have
return [...new Set(test.filter( value => ! others.has(value) ))]
}
// collect results from testing all arrays
result = []
for(const array of arrays) { result.push(...singles(array))
}
console.log(result)
Borrowing the parameter construction from #gog's excellent answer, you could also define it so that it takes a test array and an arbitrary collection of arrays to test against:
let singles = (test, ...arrays) => {
// others is the Set of all value in the other arrays
others = arrays.reduce( ( accum, elem ) => {
if (elem != test) { elem.forEach(accum.add, accum) }
return accum
}, new Set())
// find anything in the test array that the others do not have
return [...new Set(test.filter( value => ! others.has(value) ))]
}
console.log(singles(arr2, arr1, arr2, arr3))
The advantage here is that this should work with any number of arrays, while gog's answer is probably faster for a collection of less than 32 arrays (or technically any number if you were willing to extend it using BigInt, but that may lose some of the speed)
A fairly simple approach:
const inOnlyOne = (
xss,
keys = [... new Set (xss .flat ())],
uniques = xss .map (xs => new Set (xs))
) => keys .filter (k => uniques .filter (f => f .has (k)) .length == 1)
console .log (inOnlyOne ([['a', 'b', 'c', 'a', 'b'], ['a', 'd', 'b', 'c'], ['f', 'c', 'a']]))
We find the list of unique keys by flattening our array of arrays and turning that into a Set and then back into an array, convert the arrays into Sets, then filter the keys to find only those where the number of sets including that key has exactly one entry.
There is a little inefficiency here in that we check all the Sets when seeing if a number is in there. It would be easy enough to modify it to check only until we find a second Set, but the code would be more complex. I would only bother to do so if I found that this simple version was not performant enough for my needs.
One advantage of this approach is that it works for other data types than strings and numbers:
const a = {a: 1}, b = {b: 3}, c = {c: 3}, d = {d: 4}, e = {e: 5}, f = {f: 6}
inOnlyOne ([[a, b, c, a, b], [a, d, b, c], [f, c, a]])
//=> [{d: 4}, {f: 6}]
Of course that only helps if your items are shared references. If you wanted to use value equality rather than reference equality, it would be significantly more complex.
If we wanted to pass the arrays individually, rather than wrap them in a common array, this variant should work:
const inOnlyOne = (...xss) => ((
keys = [... new Set (xss .flat ())],
uniques = xss .map (xs => new Set (xs))
) => keys .filter (k => uniques .filter (f => f .has (k)) .length == 1)
) ()
The Array.prototype.includes() method seems like the way to go here.
let arr1 = ['a', 'b', 'c', 'a', 'b']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a', 'f']
var arrays = [arr1,arr2,arr3];
const items = arr1.concat(arr2, arr3);
let results = [];
items.forEach(isInOneArray);
function isInOneArray(item){
let found = 0;
for (const arr of arrays){
if (arr.includes(item)){
found ++;
}
}
if (found===1 && !results.includes(item)){
results.push(item);
}
}
console.log(results);
This is a brute force iterator much like your own, but reduces the number of re-entries by removing items from the array:
function elementsInOnlyOneArr(...arrays) {
// de-dup and sort so we process the longest array first
let sortedArrays = arrays.map(ar => [...new Set(ar)]).sort((a,b) => b.length - a.length);
for (let ai1 = 0 ; ai1 < sortedArrays.length; ai1 ++) {
for(let i = sortedArrays[ai1].length - 1; i >= 0; i --){
let exists = false;
let val = sortedArrays[ai1][i];
for(let ai2 = ai1 + 1 ; ai2 < sortedArrays.length ; ai2 ++) {
let foundIndex = sortedArrays[ai2].indexOf(val);
if (foundIndex >= 0) {
exists = true;
sortedArrays[ai2].splice(foundIndex,1);
// do not break, check for match in the other arrays
}
}
// if there was a match in any of the other arrays, remove it from the first one too!
if (exists)
sortedArrays[ai1].splice(i,1);
}
}
// concat the remaining elements, they are all unique
let output = sortedArrays[0];
for(let i = 1; i < sortedArrays.length; i ++)
output = output.concat(sortedArrays[i]);
return output;
}
let arr1 = ['a', 'b', 'c', 'a', 'b']
let arr2 = ['a', 'd', 'b', 'c']
let arr3 = ['f', 'c', 'a']
console.log(elementsInOnlyOneArr(arr1,arr2,arr3));
See this fiddle: https://jsfiddle.net/4deq7xwm/
Updated - Use splice() instead of pop()
Create a collection of pairs (x,y) where x is an element (in your case, a string) and y identifies the array it comes from. Sort this in O(log n) time by x first (where n is the total number of items over all arrays). It is easy to iterate over the result and detect the desired items.
This is easily solved with the built-in .lastIndexOf() Array method:
const arr1 = ['a', 'b', 'c', 'a', 'b'];
const arr2 = ['a', 'd', 'b', 'c'];
const arr3 = ['f', 'c', 'a'];
function getValuesInOneArray(...arrays) {
const combinedArr = arrays.flat();
const result = [];
for (const value of combinedArr) {
if (combinedArr.indexOf(value) === combinedArr.lastIndexOf(value)) {
result.push(value);
}
}
return result;
}
getValuesInOneArray(arr1, arr2, arr3); // ['d', 'f']
I generally try to avoid "ninja code" for the benefit of maintainability and readability, but I couldn't resist rewriting the above getValuesInOneArray() function as a slicker arrow function.
const getValuesInOneArray = (...arrays) =>
arrays
.flat()
.filter(
(value, index, array) => array.indexOf(value) === array.lastIndexOf(value)
);
You can read more about "ninja code" (and why you should avoid it) here, on Javacript.info, but I recommend avoiding practices like this in production codebases.
Hope this helps.
function elementsInOnlyOneArr(arr1, arr2, arr3){
let arr = arr1.concat(arr2).concat(arr3);
return removeDuplicate(arr);
}
function removeDuplicate(arr){
for(each of arr){
let count = 0;
for(ch of arr){
if(each === ch){
count++;
if(count > 1){
//removing element that exist more than one
arr = arr.filter(item => item !== each);
return removeDuplicate(arr);
}
}
}
}
return arr;
}
let arr1 = ['a', 'b', 'c', 'a', 'b'];
let arr2 = ['a', 'd', 'b', 'c'];
let arr3 = ['f', 'c', 'a'];
console.log(elementsInOnlyOneArr(arr1, arr2, arr3));
Do a diff of each of the array and concat those to get the unique values only in any one of the arrays.
const arr1 = ['a', 'b', 'c', 'a', 'b'];
const arr2 = ['a', 'd', 'b', 'c'];
const arr3 = ['f', 'c', 'a'];
function diff(a1, a2, a3) {
let u1 = a1.filter(el => { return !a2.includes(el) })
.filter(el => { return !a3.includes(el) });
let u2 = a2.filter(el => { return !a1.includes(el) })
.filter(el => { return !a3.includes(el) });
let u3 = a3.filter(el => { return !a2.includes(el) })
.filter(el => { return !a1.includes(el) });
return u1.concat(u2).concat(u3);
}
/* diff them */
const adiff = diff(arr1, arr2, arr3);
console.log(adiff);

JavaScript split and merge arrays by conditions

I have an array like [a, b, c, d] and I want to split it into 2 arrays like [a, b] and [c, d] and then merge it to have final result like [[a, b],[c, d]]. Is it possible to do without for loop?
You can use slice and push method like this
var arr = ['a', 'b', 'c', 'd'];
let index = 2;
let result = [];
result.push(arr.slice(0, index));
result.push(arr.slice(index))
console.log(result);
let arr = [0, 1, 9, 10, 8];
let arr2 = arr.slice(1,3);
let resultArr = [];
if(arr2[1] > 1){
resultArr.push(99);
}
else{
resultArr.push(100);
}
console.log(resultArr)
You might like something like this:
a = 8;
b = { some: 'say'};
c = 'life';
d = true;
let o = {
'a': [a, b, c, d],
'a1': [],
'a2': []
}
nSwitchBefore = 2;
o.a.forEach(function(item, i) {
i < nSwitchBefore ? this.a1.push(item) : this.a2.push(item) ;
}.bind(o));
console.log(o);
Within the function block there is room for extra handling your array items. Like filtering or special treatment of certain types, using all conditions you want.
yes without loop you can do this But you should know at what index you have to split the array.
var arr = ['a', 'b', 'c', 'd'];
var indexToSplit = arr.indexOf('c');
var first = arr.slice(0, indexToSplit);
var second = arr.slice(indexToSplit + 1);
var final = [first, second]
console.log(final);
I found another solution for this issue, without writing loops
Lodash Chunk does this logic
_.chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]
https://lodash.com/docs/

How to combine array to array multidimensional with object and key

How to combine 2 array to be 1 array with object and key. array1 = [a, b, c , d]
array2 = [z, y, x, w] I want to be an array like result = [[foo: a, bar: z], [foo: b, bar: y], [foo: c, bar: x], [foo: d, bar: w]]. I just can combine without object and key like this:
var array1 = [a, b, c , d];
var array2 = [z, y, x, w];
var result = [];
result = $.map(array1, function (el, idx) {
return [[el, array2[idx]]];
});
output: [[a, z],[b, y],[c, x],[d, w]];
If you want an array of objects with keys foo and bar (which it more or less looks like you do), you are almost there. You just need to make an object with map() rather than an array:
var array1 = ['a', 'b', 'c' , 'd'];
var array2 = ['z', 'y', 'x', 'w'];
let result = array1.map((item, index) => ({foo:item, bar: array2[index]}))
console.log(result)
Clean-up
First of all, a little clean-up of your initial version:
var array1 = ['a', 'b', 'c', 'd'];
var array2 = ['z', 'y', 'x', 'w'];
var result = array1.map(function (el, idx) {
return [[el, array2[idx]]];
});
console.log(result)
.as-console-wrapper {height: 100vh !important;}
Note that the array values here are listed as strings, just to show what's happening. But also note that we can use the map method of Arrays rather than jQuery's version.
Changing to objects
But now we can easily change this to get the output you are looking for:
var array1 = ['a', 'b', 'c', 'd'];
var array2 = ['z', 'y', 'x', 'w'];
var result = array1.map(function (el, idx) {
return {foo: el, bar: array2[idx]};
});
console.log(result)
.as-console-wrapper {height: 100vh !important;}
More general
The operation of pair-wise combining two lists is often called zip -- think of it like a zipper on the two lists.
We can use something much like your code to write a naive zip function:
const zip = function(xs, ys) {
return xs.map(function(x, i) {return [x, ys[i]]})
}
const array1 = ['a', 'b', 'c' , 'd'];
const array2 = ['z', 'y', 'x', 'w'];
const result = zip(array1, array2)
console.log(result)
.as-console-wrapper {height: 100vh !important;}
A general function for your problem
Combining the abstraction from this version with the expansion we used in creating objects, we could write a function zipWith that accepts the two lists as well as a function used to combine an element from each into a new value:
const zipWith = function(fn) {
return function(xs, ys) {
return xs.map(function(x, i) {return fn(x, ys[i]);})
}
}
const array1 = ['a', 'b', 'c' , 'd'];
const array2 = ['z', 'y', 'x', 'w'];
const foobar = (x, y) => ({foo: x, bar: y})
const result = zipWith(foobar)(array1, array2)
console.log(result)
.as-console-wrapper {height: 100vh !important;}
Posible extensions
This function has at least one drawback: if the lists are different lengths, your function might have to handle possible undefined values in either of its parameters. We could fix this by working only up to the length of the shorter list. This is not hard to do, but the code would not be as simple. If you are interested in that, we can work through how to do it.

Javascript Concat Values of Two Arrays

I have two arrays like this:
const a = ['a', 'b', 'c', 'd'];
const b = ['1', '2', '3', '4'];
I'm trying to make a new array like this:
const c = ['a1', 'b2', 'c3', 'd4'];
I tried it this way:
const c = [];
c.push([`${a[0]}${b[0]}`, `${a[1]}${b[1]}`, `${a[2]}${b[2]}`, `${a[3]}${b[3]}`]);
With actually looping through data and doing this took 17400ms.
I took out the c.push([........]); and it dropped to 1250ms.
Why does this take so long to do?
And what is the best way to do this?
you can use .map to achieve that. map a, then use index on each loop to get element of b.
const a = ['a', 'b', 'c', 'd'];
const b = ['1', '2', '3', '4'];
var c = a.map(function (d, i) {
return d + String(b[i])
})
console.log(c)
// ["a1", "b2", "c3", "d4"]
cleaner code using es6:
var c = a.map((d, i) => `${d}${b[i]}`)
A simple loop.
const a = ['a', 'b', 'c', 'd', 'e'];
const b = ['1', '2', '3'];
var result = [];
for (var i = 0; i < a.length; i++) {
result[i] = a[i] + b[i];
}
alert(result);
As I suspected and you confirmed, the real problem is that you do too many push.
push modifies the length of the array. The specification does not enforce any data structure for arrays, but for non-sparse ones, implementations usually use lists which store the values consecutively in memory. That's problematic when you change the length of the array, because the additional data could not fit in the place in memory where the data currently is, so all data must be moved. push ends up being constant in amortized time instead of just constant.
However, if you know the length of the resulting array beforehand, it's usually better to preallocate.
Then, instead of
var array = [];
for(var i=0; i<2e4; ++i)
array.push([a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3]]);
I would use
var array = new Array(2e4);
for(var i=0; i<2e4; ++i)
array[i] = [a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3]];

Print two arrays side by side in a multidimensional array Javascript

This is my code:
function chunk(arr, size) {
answer = [['']['']];
firstHalf = arr.slice(0,size);
secondHalf = arr.slice(size, arr.length);
return firstHalf;
}
chunk(['a', 'b', 'c', 'd'], 2);
My goal is to print the two cut up arrays side by side. I'm looking for a result like this:
[[ 'a', 'b' ],[ 'c', 'd' ]]
I know I need to push the two seperate arrays somehow, but I can't seem to get it to work.
Here is one way to create the data structure you're looking for. The modified function returns an array with your two split arrays in it.
function chunk(arr, size) {
var firstHalf = arr.slice(0,size);
var secondHalf = arr.slice(size, arr.length);
return [firstHalf, secondHalf];
}
var out = chunk(['a', 'b', 'c', 'd'], 2);
console.log(out);
Here is one way you can create and use a multi-dimensional array in JavaScript. There are better ways to do this. I have used the simplest method because you said you are new to programming.
function chunk(arr, size) {
var answer = []
firstHalf = arr.slice(0,size);
secondHalf = arr.slice(size, arr.length);
answer.push(firstHalf);
answer.push(secondHalf);
console.log(answer);
}
chunk(['a', 'b', 'c', 'd'], 2);
function chunk(arr, size) {
var answer = [];
var firstHalf = arr.slice(0,size);
answer.push(firstHalf);
var secondHalf = arr.slice(size, arr.length);
answer.push(secondHalf);
return answer;
}
var myArray = chunk(['a', 'b', 'c', 'd'], 2); // myArray === [['a','b'],['c','d']]

Categories

Resources