This question already has answers here:
Transposing a 2D-array in JavaScript
(25 answers)
Closed 7 years ago.
I have an array:
[
[1,2,3],
[4,5,6]
]
How can I turn it into
[
[1,4],
[2,5],
[3,6]
]
I am sure it's something I can do easily with lodash but I have not found it in the docs.
a solution using lodash
m = [ [1,2,3], [4,5,6] ];
t = _.zip.apply(_, m);
// result t = [ [1,4], [2,5], [3,6] ]
m = [ [1,1,1,1], [2,2,2,2], [3,3,3,3] ]
t = _.zip.apply(_, m);
// result t = [ [1,2,3], [1,2,3], [1,2,3], [1,2,3] ]
explanation:
apply: Make the call to a function with a given value for this and arguments passed as an array ..... is same that _.zip(arg0, arg1, arg2) similar _.zip.apply(null, m) where m = [arg0, arg1, arg2]
_.zip(['fred', 'barney'], [30, 40], [true, false]);
// → [['fred', 30, true], ['barney', 40, false]]
// Official documentation
Official documentation.
https://lodash.com/docs#zip
Related
This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 1 year ago.
Recently, I was trying to create three-level deep nested arrays. Crazy, I know, but it was the best solution to my problem I could think of. The arrays are created with the following code.
const lengths = [2, 3];
const arrays = lengths.map((v, i) => {
return Array(lengths[i]).fill([]);
});
arrays[0][0].push(1);
console.log(arrays);
// Expected: [ [ [ 1 ], [] ], [ [], [], [] ] ]
// Actual: [ [ [ 1 ], [ 1 ] ], [ [], [], [] ] ]
As you can see, I only push to array[0][0]. Yet, both [0][0] and [0][1] get pushed to. What is going on here? Is it a bug, or a feature? Some kind of weird memory management?
If it helps, I am using Node.js. Thanks in advance.
You are filling the entire array with the same array reference. Instead, you could use the mapping callback of Array.from to rectify this issue by returning a different array each time.
const lengths = [2, 3];
const arrays = lengths.map((v, i) => {
return Array.from({length: lengths[i]}, _=>[]);
});
arrays[0][0].push(1);
console.log(arrays);
.as-console-wrapper{top:0;max-height:100%!important}
This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 3 years ago.
I have a list of sounds like so:
[
[ 'b', 'v' ],
[ 'a' ],
[ 'n', 't' ]
]
I need to produce a list of all combinations there sounds can make. The desired output is:
[
'ban',
'van',
'bat',
'vat'
]
The best I have been able to come up with so far is a hard-coded solution but the solution must be flexible to accommodate any length of array. Any ideas? thx
You could recursively traverse the combinations and yield the results through a generator:
function* combine([head, ...tail], previous = []) {
for(const v of head) {
if(tail.length) {
yield* combine(tail, [...previous, v]);
} else yield [...previous, v];
}
}
// Then just do
console.log(
[...combine(["bv", "a", "nt"])].map(it => it.join(""))
);
This question already has answers here:
Convert Array to Object
(46 answers)
Closed 4 years ago.
I have an array of arrays that I want to turn into an array of objects in JavaScript.
Input:
[
[ "foo", 1.0 ],
[ "bar", 3.2 ],
[ "baz", 2.1 ]
]
Output:
[
{ "foo": 1.0 },
{ "bar": 3.2 },
{ "baz": 2.1 }
]
Use array.map to do something like this perhaps:
arr = [
["foo", 1.0],
["bar", 3.2],
["baz", 2.1]
]
console.log(arr.map(e => ({[e[0]]: e[1]})));
This code will work on All the browsers:
Plain native code for the understanding of conversion(code is not optimized though):
var ArrayObject = [
["foo", 1.0],
["bar", 3.2],
["baz", 2.1]
];
var OutputArray = []
for(var i=0;i<ArrayObject.length;i++){
var arrayObject = {}
var ObjectProperty = ArrayObject[i][0];
var ObjectValue = ArrayObject[i][1];
arrayObject[ObjectProperty] = ObjectValue;
OutputArray.push(arrayObject);
}
I volunteer teaching coding to young girls to code and one of the more advanced ones was trying to use a 2D array for her JavaScript project, but was struggling with the concept of multidimensional arrays. I started putting together a tutorial on arrays and multidimensional arrays to review with her next week, got a little carried away with writing a matrix searching demo, and then realized I don't know a great way of deep copying or creating filled multidimensional arrays that copy the potentially variable-length dimensions of another array (e.g., for storing visited cell data when searching) in JavaScript, which I've only really learned/used within the last year-ish. This is what I came up with:
/**
* #param mdArray A multidimensional array that may contain variable length arrays
* #param fillValue The value to fill the cells with
*
* #return A multidimensional array with the same dimensions as mdArray where
* each cell is filled with fillValue
*/
function createFilledMultidimensionalArray(mdArray, fillValue) {
// Create a new array with mdArray.length rows
return new Array(mdArray.length).fill().map( function (elt, row) {
// Populate each row with a new filled array containing fillValue
return new Array(mdArray[row].length).fill(fillValue);
}
);
}
/**
* #param mdArray A multidimensional array that may contain variable length arrays
*
* #return A deep copy of mdArray
*/
function multidimensionalArrayCopy(mdArray) {
return JSON.parse(JSON.stringify(mdArray));
// note: I'm aware this isn't a universally perfect deep copy *shrug*
}
/* Testing */
// Create a ridiculous array containing variable-length arrays
var multidimensionalArray = [[6, { a: '1', b: 2 }], [1, 2], [3, 4, 5], ['seven']];
// Copy and print the array
var copied = multidimensionalArrayCopy(multidimensionalArray);
console.log(multidimensionalArray);
// Prints: [ [ 6, { a: '1', b: 2 } ], [ 1, 2 ], [ 3, 4, 5 ], [ 'seven' ] ]
// Modify a value
multidimensionalArray[0][1].b = 'hi';
// Print both arrays, observe copy is deep
console.log(multidimensionalArray);
console.log(copied);
/* Prints:
[ [ 6, { a: '1', b: 'hi' } ], [ 1, 2 ], [ 3, 4, 5 ], [ 'seven' ] ]
[ [ 6, { a: '1', b: 2 } ], [ 1, 2 ], [ 3, 4, 5 ], [ 'seven' ] ]
*/
// Create a new array with same dimensions as 'copied' where each cell is filled with 'false'
console.log(createFilledMultidimensionalArray(copied, false));
/* Prints:
[ [ false, false ],
[ false, false ],
[ false, false, false ],
[ false ] ]
*/
Does anyone else out there with more JS experience have any other ideas? (Please don't suggest slice, which shallow copies.)
You could use a recursive clone function instead of stringifying your data. Then for filling multi-dimension arrays, you could use a recursive deepMap function that calls itself on nested arrays:
function clone(value) {
if(Array.isArray(value)) return value.map(clone);
if(typeof value === 'object') {
return Object.entries(value).reduce((cloned, [key, value]) => {
cloned[key] = clone(value);
return cloned;
}, {});
}
return value;
}
function deepMap(array, fn) {
return array.map(value =>
Array.isArray(value)
? deepMap(value, fn)
: fn(value)
);
}
function deepFill(array, fillValue) {
return deepMap(array, () => fillValue);
}
const original = [
[1, 2, 3],
[{value: 'unchanged'}, 5, 6],
[false, true],
[7, 8, [9, 10], 11, 12],
];
const cloned = clone(original);
const filled = deepFill(original, 'fill');
cloned[1][0].value = 'changed';
console.log(
original[1][0].value,
cloned[1][0].value,
);
console.log(filled);
I want to create two arrays b and c at the same time. I know two methods which can be able to achieve it. The first method is
b = ([i, i * 2] for i in [0..10])
c = ([i, i * 3] for i in [0..10])
alert "b=#{b}"
alert "c=#{c}"
This method is very handy for creating only one array. I can not be the better way to get the better performance for computation.
The second method is
b = []
c = []
for i in [0..10]
b.push [i, i*2]
c.push [i, i*3]
alert "b=#{b}"
alert "c=#{c}"
This method seems good for computation efficiency but two lines
b = []
c = []
have to be written first. I don't want to write this 2 lines but I have not find a good idea to have the answer. Without the initialization for the arrays of b and c, we can not use push method.
There exists the existential operator ? in Coffeescript but I don't know hot to use it in this problem. Do you have a better method for creating the arrays of b and c without the explicit initialization?
Thank you!
You can use a little help from underscore (or any other lib that provides zip-like functionality):
[b, c] = _.zip ([[i, i * 2], [i, i * 3]] for i in [0..10])...
After executing it we have:
coffee> b
[ [ 0, 0 ],
[ 1, 2 ],
[ 2, 4 ],
[ 3, 6 ],
[ 4, 8 ],
[ 5, 10 ],
[ 6, 12 ],
[ 7, 14 ],
[ 8, 16 ],
[ 9, 18 ],
[ 10, 20 ] ]
coffee> c
[ [ 0, 0 ],
[ 1, 3 ],
[ 2, 6 ],
[ 3, 9 ],
[ 4, 12 ],
[ 5, 15 ],
[ 6, 18 ],
[ 7, 21 ],
[ 8, 24 ],
[ 9, 27 ],
[ 10, 30 ] ]
See the section about splats in CoffeeScript docs for more details and examples.
How about this using the existential operator:
for i in [0..10]
b = [] if not b?.push [i, i*2]
c = [] if not c?.push [i, i*3]
console.log "b=#{b}"
console.log "c=#{c}"
Or to be a bit more understandable:
for i in [0..10]
(if b? then b else b = []).push [i, i*2]
(if c? then c else c = []).push [i, i*3]
console.log "b=#{b}"
console.log "c=#{c}"
EDIT: from comments:
OK but you you have to write so many tedious codes. The same reason is
also for ` (b = b or []).push [i, i*2]
It is tedious, so we can wrap it in a function (but beware the variables will be global now):
# for node.js
array = (name) -> global[name] = global[name] or []
# for the browser
array = (name) -> window[name] = window[name] or []
for i in [0..10]
array('b').push [i, i*2]
array('c').push [i, i*3]
console.log "b=#{b}"
console.log "c=#{c}"