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}
Related
I have two arrays I'm trying to combine in a very specific way and I need a little guidance. Array1 is an array of dates 30-40 items, Array 2 is a list of objects with a date inside one of the attributes. I'm trying to append the object in array 2 to the index of array1 when the dates match.
I want to put arr2 in the same index as arr1 if the dates match.
const arr = [
"2022-06-26T07:00:00.000Z",
"2022-06-27T07:00:00.000Z",
"2022-06-28T07:00:00.000Z",
"2022-06-29T07:00:00.000Z",
"2022-06-30T07:00:00.000Z",
"2022-07-01T07:00:00.000Z",
"2022-07-02T07:00:00.000Z",
"2022-07-03T07:00:00.000Z",
"2022-07-04T07:00:00.000Z",
"2022-07-05T07:00:00.000Z",
"2022-07-06T07:00:00.000Z",
"2022-07-07T07:00:00.000Z",
"2022-07-08T07:00:00.000Z",
"2022-07-09T07:00:00.000Z",
"2022-07-10T07:00:00.000Z",
"2022-07-11T07:00:00.000Z",
"2022-07-12T07:00:00.000Z",
"2022-07-13T07:00:00.000Z",
"2022-07-14T07:00:00.000Z",
"2022-07-15T07:00:00.000Z",
"2022-07-16T07:00:00.000Z",
"2022-07-17T07:00:00.000Z",
"2022-07-18T07:00:00.000Z",
"2022-07-19T07:00:00.000Z",
"2022-07-20T07:00:00.000Z",
"2022-07-21T07:00:00.000Z",
"2022-07-22T07:00:00.000Z",
"2022-07-23T07:00:00.000Z",
"2022-07-24T07:00:00.000Z",
"2022-07-25T07:00:00.000Z",
"2022-07-26T07:00:00.000Z",
"2022-07-27T07:00:00.000Z",
"2022-07-28T07:00:00.000Z",
"2022-07-29T07:00:00.000Z",
"2022-07-30T07:00:00.000Z",
"2022-07-31T07:00:00.000Z",
"2022-08-01T07:00:00.000Z",
"2022-08-02T07:00:00.000Z",
"2022-08-03T07:00:00.000Z",
"2022-08-04T07:00:00.000Z",
"2022-08-05T07:00:00.000Z",
"2022-08-06T07:00:00.000Z"
]
const arr2 = [
{
"gsi1SK": "name ",
"searchPK": "thing",
"SK": "uuid",
"Desc": "place #1205",
"PK": "thing uuid",
"searchSK": "7/1/2022",
"gsi1PK": "thing",
"Complete": false,
"Users": [
"person1",
"person2"
]
},
{
"gsi1SK": "name",
"searchPK": "thing",
"SK": "uuid",
"Desc": "place#124124",
"PK": "thing uuid",
"searchSK": "7/4/2022",
"gsi1PK": "thing",
"Complete": false,
"Users": [
"person2",
"person45"
]
}
]
console.log([arr, arr2]);
You seem to have a handle on the date conversion part. Here I've defined two short sample arrays to represent arr2 and newArr. Then, a map function to create the output.
const arr2 = [
{
"OTHER_FIELDS": "TOP SECRET",
"searchSK":"7/4/2022"
},
{
"OTHER_FIELDS": "TOP SECRET",
"searchSK":"7/9/2022"
}
];
const newArr = [
[
"7/2/2022"
],
[
"7/3/2022"
],
[
"7/4/2022"
],
[
"7/5/2022"
],
[
"7/6/2022"
],
[
"7/7/2022"
],
[
"7/8/2022"
],
[
"7/9/2022"
],
[
"7/10/2022"
]
];
// for each subarray in newArr, return an array containing the existing element plus any elements from arr2 found by the filter function
const output = newArr.map(el => [...el, ...arr2.filter(a2 => a2.searchSK === el[0])]);
console.log(output);
Plan
You've got two obvious options:
A. Look at each of the objects, finding a home for each one in turn
B. Look at each of the dates, collecting all the objects that belong to it
Which method makes more sense for you will depend on other factors you haven't covered in your post. I think the main question is: is it guaranteed that the date list will contain a proper home for every object? If no, then do you want to drop the objects without proper homes, or do you want to create a proper home for the objects
Performance can also matter, but really only if you expect either list to be very long or if you need to run this process multiple times (such as in a React component in the browser).
Implement
Loop through the list you chose. For each item, scan the other list for the relevant item(s): its home or its children. Take the appropriate action for those items depending on which plan you chose.
Another consideration is: don't mutate your arguments. That means you probably need to create copies of the two input arrays before you do the work. If the arrays contain objects rather than scalars, you can't just do array.slice() to create a copy.
For an array of POJOs, you can convert the source to a string and then back again to create a clone.
The array of dates will need special handling, because JSON.parse will not revive dates.
Mutating arguments is generally a bad practice, at least in the functional paradigm that underlies many popular front-end frameworks today. Plus, if you create your own copies of the input data, you can gain efficiency by moving items from the source arrays to the output array, which means that subsequent iterations won't have to re-examine items that have already been processed.
This question already has answers here:
How to merge two array of objects with reactjs?
(4 answers)
Closed 11 months ago.
how to merge array of this in react or javascript..can anyone help me with this i want the output something like..all the test array should be in one array...coz i need to find the minimum price and plus i need to show the mapping in ascending order
array :[
{
id:0,
name:'something',
test: [
{
id: 0,
test_name:'blood',
price:'200',
},
{
id:1,
test_name:'kidney',
price:'300',
}
]
},
{
id:1,
name:'something1',
test: [
{
id: 0,
test_name:'blood2',
price:'100',
},
{
id:1,
test_name:'kidney2',
price:'100',
}
]
}
]
You can use spread operator to merge two array.
var a = [{fname : 'foo'}]
var b = [{lname : 'bar'}]
var c = [...a, ...b] // output is [{fname : 'foo'},{lname : 'bar'}]
I want to convert this:
[null, 1890, null, NGU]
...into this:
[[], [1890], [], [NGU]]
I've tried creating a new array and pushing values to it, but that just ends up looking the same. Honestly, I'm unsure of what to even call what I'm trying to create. Is it a two-dimensional array or an array of objects?
This is for a google app script and the documentation calls it a two-dimensional array of values.
var arr = [null, 1890, null, 'NGU']
var arr2d = arr.map(x => [x])
console.log(arr2d) // output --> [ [ null ], [ 1890 ], [ null ], [ 'NGU' ] ]
This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed 4 years ago.
I have an array of json objects:
[ {id:0, name:'A'}, {id:1, name:'B'}...{id:n, name:'N'} ]
How do i get the value (name) base on a given id, without iterating the array? Perhaps using map or some filter method...
const arr = [ {id:0, name:'A'}, {id:1, name:'B'},{id:3, name:'N'} ];
const inputId = 1;
const foundObj = arr.find(({ id }) => id === inputId);
if (foundObj) console.log(foundObj.name);
This still does iterate the array internally, though (as any method will).
This find method will find object based on your object property and value.
ArrayName.find(x => x.id === 0);
let array = [ {id:0, name:'A'}, {id:1, name:'B'}, {id:'n', name:'N'} ]
//To search in array we must iterate. But if you want to optimise performance for multiple searches you can map it to object by id.
let map = array.reduce((acc,element)=>{acc[element.id]=element;return acc;},{})
console.log(map[0])
console.log(map[1])
console.log(map.n) //As n was used as id.
Maps take one iteration to construct. Value retrieval thereon is sublinear.
// Input.
const input = [{id: 0, name:'A'}, {id: 1, name:'B'}, {id: 13, name:'N'}]
// To Map.
const toMap = (A) => new Map(A.map(x => [x.id, x]))
// Output.
const output = toMap(input)
// Proof.
console.log(output.get(0))
console.log(output.get(1))
console.log(output.get(13))
When you want to find an element in a collection, array might not be the best choice, objects or maps are much better in that case.
Each time you have to find an element, you would have to iterate over the array which would take O(n) time.
To avoid this, you could have an API layer in the middle, to convert your array into an a data structure which maps values by unique keys. You could achieve this by a plain Javascript Object.
That way you could find your element by id in O(1) without any iteration.
//original data
let arr = [ {id:0, name:'A'}, {id:1, name:'B'}, {id:2, name:'N'} ];
//convert it into object
let obj = arr.reduce((acc, curr) => {
acc[curr.id] = curr;
return acc;
}, {});
//modified data
{ 0: { id: 0, name: 'A' },
1: { id: 1, name: 'B' },
2: { id: 2, name: 'N' } }
//Now, you can look up value on any id as
obj[id].name;
I am trying to test if my deep clone of an array is identic to the original object (jQuery available).
Here is how I clone it
self.slides = jQuery.extend(true, {}, parent.modules[self.moduleId].composed);
However, I end up with two slightly different objects, so even if the actual content that I am concerned with is identic, these two objects aren't. If I dump them in chrome console, this is how they look:
Original object:
[Object]
0: Object
length: 1
__proto__: Array[0]
Clone:
Object {0: Object}
0: Object
__proto__: Object
So the clone appears to actually be an object (or an object of type object) while the original seem to be an array (or object of type array).
Is there another way of cloning or how can I perform this identic-test?
Simplest way to clone any object would be
var array1 = [1, [2], 3];
var array2 = JSON.parse(JSON.stringify(array1));
You can check them like this
console.log(array1, array2);
// [ 1, [ 2 ], 3 ] [ 1, [ 2 ], 3 ]
array1[1][0] += 3;
console.log(array1, array2);
// [ 1, [ 5 ], 3 ] [ 1, [ 2 ], 3 ]
this occurs because you are passing an object "{}" extender to try to clone this way, I believe it is much better
var clone = myArray.slice(0);