I have two arrays and I want to form an array of objects such that the new array of obj has two keys with first key being filled with elements of first array and second key having arrays elements of second array. Can this be done using the map function. I found the closest answer as this:-
Merge two arrays into an array of objects with property values
eg.:-
ar1=[];
ar2=[];
armixed=[{ar1element,ar2element},{}......]
But it uses angular JS I just want to use pure JS.
I'm not sure what your output should be but the one you provided seems invalid. I have modified the output format to be valid.
For the task you have the solution is to zip the arrays, however, JS has no inbuilt zip function, so we can emulate it via map function:
var ar1 = ['a1', 'a2', 'a3', 'a4', 'a5'];
var ar2 = ['b1', 'b2', 'b3', 'b4', 'b5'];
var armixed = ar1.map(function (x, i) {
return [x, ar2[i]]
});
Output will be:
armixed = [
["a1", "b1"]
["a2", "b2"]
["a3", "b3"]
["a4", "b4"]
["a5", "b5"]
]
If you want objects in your output (rather than arrays), you can just edit the return statement above to something like:
return { categories: x, catid: ar2[i] }
Just to clarify, do you want an object for each unique possible combination of the arrays? If so, nesting two map functions should do the trick:
let newArray = [{}]
arr1.map(i => {
arr2.map (j => {
newArray.push({prop1: i, prop2: j})
})
})
Related
I've seen multiple similar questions to this, but I can't figure out how to apply the proposed solutions to a slightly different data structure.
Here's an array of named objects that need to be sorted numerically by the property count:
const myArray = [
{ABC:{label:'ABC', count:3}},
{EFG:{label:'EFG', count:10}},
{DEF:{label:'DEF', count:9}},
{FGH:{label:'FGH', count:1}}
]
And the resulting array after sorting should be like this:
myArray = [
{FGH:{label:'FGH', count:1}},
{ABC:{label:'ABC', count:3}},
{DEF:{label:'DEF', count:9}},
{EFG:{label:'EFG', count:10}}
]
If the objects didn't have a name (ABC, DEF, etc) then the MDN web docs (along with multiple similar questions here) contain the solution for sorting such an array.
That is, consider a slightly different array of unnamed objects:
const myArray1 = [
{label:'ABC', count:3},
{label:'EFG', count:10},
{label:'DEF', count:9},
{label:'FGH', count:1}
]
This one-liner works: myArray1.sort((a, b) => a.count - b.count) to obtain:
myArray1 = [
{label:'FGH', count:1},
{label:'ABC', count:3},
{label:'DEF', count:9},
{label:'EFG', count:10}
]
I know a more complex function expression is necessary to handle this, but I just don't know the language well enough (yet) to figure it out.
Just take the first (and only) object value first before comparing.
const myArray = [
{ABC:{label:'ABC', count:3}},
{EFG:{label:'EFG', count:10}},
{DEF:{label:'DEF', count:9}},
{FGH:{label:'FGH', count:1}}
]
const getCount = obj => Object.values(obj)[0].count;
myArray.sort((a, b) => getCount(a) - getCount(b));
console.log(myArray);
I know that if there is an array of values it must be used this approach:
console.log(['joe', 'jane', 'mary'].includes('jane')); // true
But in case of an array of arrays, is there a short way to do it? Without other computations between.
For this input:
[['jane'],['joe'],['mary']]
You can use flat method to flatten the array. For more neted array, you can also mention depth like flat(depth)
let arr = [["jane"],["joe"],["mary"]];
arr.flat().includes('jane'); //true
You can easily achieve this result using some
arr.some((a) => a.includes("jane"))
const arr = [
["jane"],
["joe"],
["mary"]
];
const arr2 = [
["joe"],
["mary"]
];
console.log(arr.some((a) => a.includes("jane")));
console.log(arr2.some((a) => a.includes("jane")));
it can also be done by first flattening the 2d arrays in 1 d aaray and then using includes to find whether the array contains the element or not
var arr = [['jane'],['joe'],['marry']]
var newarr=[].concat(...arr)
var v=newarr.includes('jane')
console.log(v)
In its most basic form, having an array of objects:
let arr = [
{val:"a"},
{val:"b"}
];
How can destructuring be used, to obtain only the values ['a', 'b'].
getting the first value is easy:
let [{val:res}] = arr; //res contains 'a'
Obtaining all values inside the array can be done with the rest operator:
let [...res] = arr; //res contains all objects
Combining those, I expected to be able to use:
let [...{val:res}] = arr; //undefined, expected all 'val's (['a', 'b'])
The above returns undefined (Tested in FF). Some further testing seems to indicate that adding the rest operator when using an object destructuring as well doesn't use the iteration, but gets back the original object, e.g. let [...{length:res}] = arr; //res= 2. Some other trials, such as let [{val:...res}] = arr; or let [{val}:...res] = arr; produce syntax errors.
It's easy enough to do with other methods, such as using map on the array, but mostly I stumble upon this problem while destructuring multiple levels (an array with objects which have their own property containing an array). Therefore I'm really trying to get around how to do it solely with destructuring.
For convenience: a test fiddle
edit
My apologies if I failed to explain the goal of the question. I'm not looking for a solution to a specific problem, only to find the correct syntax to use when destructuring.
Otherwise formulated, a first question would be: in the example above, why doesn't let [...{val:res}] = arr; return all values (['a', 'b']). The second question would be: what is the proper syntax to use a rest operator with a nested object destructuring? (pretty sure I've gotten some definitions mixed up here). It seems that the latter is not supported, but I haven't come across any documentation that (and why) it wouldn't be.
Why doesn't let [...{val:res}] = arr; return all values (['a', 'b'])?
You seem to confuse the rest syntax with array comprehensions.
If you assign a value to [someElements, ...someExpression], the value is tested to be iterable and then each element generated by the iterator is assigned to the respective someElements variable. If you use the rest syntax in the destructuring expression, an array is created and the iterator is ran till its end while filling the array with the generated values. Then that array is assigned to the someExpression.
All of these assignment targets can be other destructuring expressions (arbitrarily nested and recursively evaluated), or references to variable or properties.
So if you do let [...{val:res}] = arr, it will create an array and fill that with all the values from the iterator of arr:
let {val:res} = Array.from(arr[Symbol.iterator]())
You can see now why that ends up with undefined, and why using something like [...{length:res}] does yield a result. Another example:
let [{val:res1}, ...{length: res2}] = arr;
console.log(res1) // 'a'
console.log(res2) // 1 (length of `[{val: 'b'}]`)
How can destructuring be used to obtain only the values ['a', 'b']?
Not at all. Use the map method.
You can destructure nested objects like this
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Nested_object_and_array_destructuring
let arr = [
{val:"a"},
{val:"b"}
];
const [{val: valueOfA}, {val: valueOfB}] = arr
console.log(
valueOfA, valueOfB
)
Beside mapping with a callback for the value
let arr = [{ val: "a" }, { val: "b" }];
console.log(arr.map(o => o.val));
you could use deconstructiong inside of the paramter list and use only the value to return.
let arr = [{ val: "a" }, { val: "b" }];
console.log(arr.map(({val}) => val));
At this point of time you can use both For of loop with ES6 Object destructuring.
let arr = [{val:"a"},{val:"b"}];
for (const item in arr){
const {val} = arr[item];
console.log(val);
}
You can declare assignment target before destructuring assignment; at destructuring target, set values of assignments target indexes by from destructuring source
let arr1 = [{val: "a"}, {val: "b"}];
let arr2 = [{"foo":1,"arr":[{"val":"a"},{"val":"b"}]}
, {"foo":2,"arr":[{"val":"c"},{"val":"d"}]}];
let [res1, res2] = [[], []];
[{val: res1[0]}, {val: res1[1]}] = arr1;
[{arr: [{val:res2[0]}, {val:res2[1]}]}
, {arr: [{val:res2[2]}, {val:res2[3]}]}] = arr2;
console.log(res1, res2);
You can alternatively use rest element at target to collect values at source by including comma operator following object pattern to return value pulled from object
let arr = [{val: "a"}, {val: "b"}];
let [...res] = [({val} = arr[0], val), ({val} = arr[1], val)];
console.log(res)
Hi I have following objects in an array and they appear like this:
[{col1:abc}
{col2:def}
{col1:ghi}]
What I want to do is if the same key is coming again I should overwrite it so it becomes
[{col1:ghi}
{col2:def}]
instead of appending another key value pair.
I am thinking of something like to overwrite
[col1:{col1:ghi}
col2:{col2:def}]
so that i can easily iterate over them in future.
Is there any way to put my keys in this way by using map or something similar?
Thank you
I'm going to assume all your objects look like the ones you provided in your question, i.e. they each are a single key-value pair (like {col1: "abc"})
We first need to loop over all the objects in your array, combining them into one large object. Since an object cannot have two identical keys, this has the effect of overwriting values associated with a key that occur earlier in the array with ones that associate with the same key, but occur later. This can be achieved with:
const unifiedObj = arr.reduce((acc, obj) => Object.assign(acc, obj), {})
reduce is a way of "looping" over the items in an array (well, not exactly, but you can think of it this way for now). Object.assign is a way to merge two objects. You should look these up in the MDN docs.
So now, if your original array looked like this:
[
{col1:"abc"}
{col2:"def"}
{col1:"ghi"}
]
The "unified" object will look like this:
{
col1: "ghi",
col2: "def"
}
Next, since you want an array of 'single key-value pair objects' as your final result, instead of this unified object, we're going to have to extract each key-value pair in the unified object into a new object, and collect all those new objects into an array. That's what this statement does.
const result = Object.keys(unifiedObj).map(k => ({k: unifiedObj[k]}))
Object.keys gives you all the keys of an object as an array. map transforms an array into another array, using the function supplied as its argument. Look these up too.
At the end, result will be an array that looks like this:
[
{ col1: "ghi" },
{ col2: "def" }
]
which seems to be what you wanted. Do note that the objects in the array might be in a different order from what you expect, i.e. the final array may also look like this:
[
{ col2: "def" },
{ col1: "ghi" }
]
This is quite an easy task! The explanation is in the code comments.
const arr = [{col1:'abc'},
{col2:'def'},
{col1:'ghi'}]
arr.forEach((item, index) => {
// get the key `col1`, `col2` etc. (only works if there is one key in the object!)
const key = Object.keys(item)[0]
// now check if the key was previously encountered
for (i = 0; i < index; i++) {
if (arr[i][key] !== undefined) {
// the same key was found in the already processed chunk of the array! Rewrite it with the latter value!
arr[i][key] = item
}
}
})
console.log(arr)
I think you probably want to produce a single object from your array of objects and retain all values for the same key, so that
[
{col1: 'abc'},
{col2: 'def'},
{col1: 'ghi'}
]
becomes
{
col1: ['abc', 'ghi'],
col2: ['def']
}
if that sounds right, then here's how to do it:
const arr = [
{col1: 'abc'},
{col2: 'def'},
{col1: 'ghi'}
];
const result = arr.reduce((memo, o) => {
Object.entries(o).forEach(([key, val]) => {
memo[key] = memo[key] || [];
memo[key].push(val);
});
return memo;
}, {});
console.log(result)
In its most basic form, having an array of objects:
let arr = [
{val:"a"},
{val:"b"}
];
How can destructuring be used, to obtain only the values ['a', 'b'].
getting the first value is easy:
let [{val:res}] = arr; //res contains 'a'
Obtaining all values inside the array can be done with the rest operator:
let [...res] = arr; //res contains all objects
Combining those, I expected to be able to use:
let [...{val:res}] = arr; //undefined, expected all 'val's (['a', 'b'])
The above returns undefined (Tested in FF). Some further testing seems to indicate that adding the rest operator when using an object destructuring as well doesn't use the iteration, but gets back the original object, e.g. let [...{length:res}] = arr; //res= 2. Some other trials, such as let [{val:...res}] = arr; or let [{val}:...res] = arr; produce syntax errors.
It's easy enough to do with other methods, such as using map on the array, but mostly I stumble upon this problem while destructuring multiple levels (an array with objects which have their own property containing an array). Therefore I'm really trying to get around how to do it solely with destructuring.
For convenience: a test fiddle
edit
My apologies if I failed to explain the goal of the question. I'm not looking for a solution to a specific problem, only to find the correct syntax to use when destructuring.
Otherwise formulated, a first question would be: in the example above, why doesn't let [...{val:res}] = arr; return all values (['a', 'b']). The second question would be: what is the proper syntax to use a rest operator with a nested object destructuring? (pretty sure I've gotten some definitions mixed up here). It seems that the latter is not supported, but I haven't come across any documentation that (and why) it wouldn't be.
Why doesn't let [...{val:res}] = arr; return all values (['a', 'b'])?
You seem to confuse the rest syntax with array comprehensions.
If you assign a value to [someElements, ...someExpression], the value is tested to be iterable and then each element generated by the iterator is assigned to the respective someElements variable. If you use the rest syntax in the destructuring expression, an array is created and the iterator is ran till its end while filling the array with the generated values. Then that array is assigned to the someExpression.
All of these assignment targets can be other destructuring expressions (arbitrarily nested and recursively evaluated), or references to variable or properties.
So if you do let [...{val:res}] = arr, it will create an array and fill that with all the values from the iterator of arr:
let {val:res} = Array.from(arr[Symbol.iterator]())
You can see now why that ends up with undefined, and why using something like [...{length:res}] does yield a result. Another example:
let [{val:res1}, ...{length: res2}] = arr;
console.log(res1) // 'a'
console.log(res2) // 1 (length of `[{val: 'b'}]`)
How can destructuring be used to obtain only the values ['a', 'b']?
Not at all. Use the map method.
You can destructure nested objects like this
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Nested_object_and_array_destructuring
let arr = [
{val:"a"},
{val:"b"}
];
const [{val: valueOfA}, {val: valueOfB}] = arr
console.log(
valueOfA, valueOfB
)
Beside mapping with a callback for the value
let arr = [{ val: "a" }, { val: "b" }];
console.log(arr.map(o => o.val));
you could use deconstructiong inside of the paramter list and use only the value to return.
let arr = [{ val: "a" }, { val: "b" }];
console.log(arr.map(({val}) => val));
At this point of time you can use both For of loop with ES6 Object destructuring.
let arr = [{val:"a"},{val:"b"}];
for (const item in arr){
const {val} = arr[item];
console.log(val);
}
You can declare assignment target before destructuring assignment; at destructuring target, set values of assignments target indexes by from destructuring source
let arr1 = [{val: "a"}, {val: "b"}];
let arr2 = [{"foo":1,"arr":[{"val":"a"},{"val":"b"}]}
, {"foo":2,"arr":[{"val":"c"},{"val":"d"}]}];
let [res1, res2] = [[], []];
[{val: res1[0]}, {val: res1[1]}] = arr1;
[{arr: [{val:res2[0]}, {val:res2[1]}]}
, {arr: [{val:res2[2]}, {val:res2[3]}]}] = arr2;
console.log(res1, res2);
You can alternatively use rest element at target to collect values at source by including comma operator following object pattern to return value pulled from object
let arr = [{val: "a"}, {val: "b"}];
let [...res] = [({val} = arr[0], val), ({val} = arr[1], val)];
console.log(res)