Merging multiple arrays inside a array of objects into a single array - javascript

I have a object where data is an array of objects, inside data object I have one users property which is an array.
I need to get all the users into a single array. I have written using map and concat.
Is there any way I can have a better solution, or this is correct?
See the below snippet.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var users = response.data.map(o => o.users)
const usersCollection = [].concat(...users)
console.log(usersCollection)

You can use Array.prototype.flat():
The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.
depth | Optional
The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var users = response.data.map(o => o.users).flat();
console.log(users);
You can also try with Array.prototype.flatMap() which is identical to a map followed by a call to flat of depth 1.
var users = response.data.flatMap(o => o.users);

If Using ES6, utilizing the power of spread with Array.reduce
var response = {
data: [{
users: [1, 2, 3]
}, {
users: [4, 5, 6]
}]
}
var users = response.data.reduce((accumulator, obj) => [...accumulator, ...obj.users], []);
console.log(users);

Using ES6 Spread operator you can do the job quick.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
let wantedArray = [];
for(let v of response.data){
wantedArray.push(...v.users);
}
console.clear();
console.log(wantedArray);

The flatMap() method first maps each element using a mapping function,
then flattens the result into a new array. It is identical to a map
followed by a flat of depth 1, but flatMap is often quite useful, as
merging both into one method is slightly more efficient
response.data.flatMap(({users})=>users)
You should be careful with vendor support though if you’re running in the browser.

You can use ES6 spread operator
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var NEWARRAY = [];
for(var v of response.data){
NEWARRAY.push(...v.users);
}
console.log(NEWARRAY);

Related

Set and spread operator [duplicate]

Set seems like a nice way to create Arrays with guaranteed unique elements, but it does not expose any good way to get properties, except for generator [Set].values, which is called in an awkward way of mySet.values.next().
This would have been ok, if you could call map and similar functions on Sets. But you cannot do that, as well.
I've tried Array.from, but seems to be converting only array-like (NodeList and TypedArrays ?) objects to Array. Another try: Object.keys does not work for Sets, and Set.prototype does not have similar static method.
So, the question: Is there any convenient inbuilt method for creating an Array with values of a given Set ? (Order of element does not really matter).
if no such option exists, then maybe there is a nice idiomatic one-liner for doing that ? like, using for...of, or similar ?
if no such option exists, then maybe there is a nice idiomatic
one-liner for doing that ? like, using for...of, or similar ?
Indeed, there are several ways to convert a Set to an Array:
Using Array.from:
Note: safer for TypeScript.
const array = Array.from(mySet);
Simply spreading the Set out in an array:
Note: Spreading a Set has issues when compiled with TypeScript (See issue #8856). It's safer to use Array.from above instead.
const array = [...mySet];
The old-fashioned way, iterating and pushing to a new array (Sets do have forEach):
const array = [];
mySet.forEach(v => array.push(v));
Previously, using the non-standard, and now deprecated array comprehension syntax:
const array = [v for (v of mySet)];
via https://speakerdeck.com/anguscroll/es6-uncensored by Angus Croll
It turns out, we can use spread operator:
var myArr = [...mySet];
Or, alternatively, use Array.from:
var myArr = Array.from(mySet);
Assuming you are just using Set temporarily to get unique values in an array and then converting back to an Array, try using this:
_.uniq([])
This relies on using underscore or lo-dash.
Perhaps to late to the party, but you could just do the following:
const set = new Set(['a', 'b']);
const values = set.values();
const array = Array.from(values);
This should work without problems in browsers that have support for ES6 or if you have a shim that correctly polyfills the above functionality.
Edit: Today you can just use what #c69 suggests:
const set = new Set(['a', 'b']);
const array = [...set]; // or Array.from(set)
Use spread Operator to get your desired result
var arrayFromSet = [...set];
The code below creates a set from an array and then, using the ... operator.
var arr=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,];
var set=new Set(arr);
let setarr=[...set];
console.log(setarr);
SIMPLEST ANSWER
just spread the set inside []
let mySet = new Set()
mySet.add(1)
mySet.add(5)
mySet.add(5)
let arr = [...mySet ]
Result: [1,5]
In my case the solution was:
var testSet = new Set();
var testArray = [];
testSet.add("1");
testSet.add("2");
testSet.add("2"); // duplicate item
testSet.add("3");
var someFunction = function (value1, value2, setItself) {
testArray.push(value1);
};
testSet.forEach(someFunction);
console.log("testArray: " + testArray);
value1 equals value2 => The value contained in the the current position in the Set. The same value is passed for both arguments
Worked under IE11.
Using Set and converting it to an array is very similar to copying an Array...
So you can use the same methods for copying an array which is very easy in ES6
For example, you can use ...
Imagine you have this Set below:
const a = new Set(["Alireza", "Dezfoolian", "is", "a", "developer"]);
You can simply convert it using:
const b = [...a];
and the result is:
["Alireza", "Dezfoolian", "is", "a", "developer"]
An array and now you can use all methods that you can use for an array...
Other common ways of doing it:
const b = Array.from(a);
or using loops like:
const b = [];
a.forEach(v => b.push(v));
the simplistic way to doing this
const array = [...new Set([1,1,2,3,3,4,5])]
console.log(array)
Here is an easy way to get only unique raw values from array. If you convert the array to Set and after this, do the conversion from Set to array. This conversion works only for raw values, for objects in the array it is not valid. Try it by yourself.
let myObj1 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
let myObj2 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
var myArray = [55, 44, 65, myObj1, 44, myObj2, 15, 25, 65, 30];
console.log(myArray);
var mySet = new Set(myArray);
console.log(mySet);
console.log(mySet.size === myArray.length);// !! The size differs because Set has only unique items
let uniqueArray = [...mySet];
console.log(uniqueArray);
// Here you will see your new array have only unique elements with raw
// values. The objects are not filtered as unique values by Set.
// Try it by yourself.
I would prefer to start with removing duplications from an array and then try to sort.
Return the 1st element from new array.
function processData(myArray) {
var s = new Set(myArray);
var arr = [...s];
return arr.sort((a,b) => b-a)[1];
}
console.log(processData([2,3,6,6,5]);
function countUniqueValues(arr) {
return Array.from(new Set(arr)).length
}
console.log(countUniqueValues([1, 2, 3, 4, 4, 4, 7, 7, 12, 12, 13]))

Javascript - Using condition with object and array

I receive a data value from a API, and I want to make a condition to deal with it. Sometimes it can comes as an array or object. I will use a simple example.
data = [1,2,3] // These values come from API
data.map(i => i++)
The problem is: Sometimes data can also comes as this
data = {
arr: [1,2,3]
}
// It evals an error in .map, because now "data" is an object
I know that I can solve it making something like this:
if(Array.isArray(data))
data.map(i => i++);
else
data.arr.map(i => i++);
But my code is not just a one line .map. Is there a way to make this simple condition without copying and paste code?
Thanks!
You can for example assign the array reference to another variable and use it in the rest of your code, like this:
let arr = Array.isArray(data) ? data : data.arr;
arr.map(i => i++)
A simple OR (||) operator is pretty idiomatic JavaScript:
(data.arr || data).map(i => ++i);
If the data.arr property is defined, that will be mapped, otherwise data itself will be mapped.
Complete snippet:
Note: the post-increment operator would have no effect, so I replaced it with a pre-increment.
let data, result;
data = [1, 2, 3];
result = (data.arr || data).map(i => ++i);
console.log(result);
data = {
arr: [1, 2, 3]
}
result = (data.arr || data).map(i => ++i);
console.log(result);
You can use the ternary operator.
Array.isArray(data)
? data.map(i => i++);
: data.arr.map(i => i++);
You can use destruction es6 , not sure its a good idea but you can achieve your functionality in single line. ;)
let { arr=data } = data;
arr.map(i => i++)
if arr key is not found in data then it will assign default data array.
Cheers
You can do it like this
You can use the ternary operator and assign the value as array directly to temp if it is an Array and if not than you assign using the property like input.arr which is an Array.
So once the value is in form of array than you can use the single map statement so you need not to repeat your map statement.
let data = [1,2,3];
let data1 = {
arr: [1,2,3]
}
function handle(input){
let temp = Array.isArray(input) ? input : input.arr
return temp.map(i => i++);
}
console.log(handle(data))
console.log(handle(data1))
If you don't wish to use an if or a ternary operator you can use Object.values(data).flat() to convert your data into:
[1, 2, 3]
This will essentially not modify your array and leave it be, however, it will compress your data object into an array form.
See working examples below:
Data form 1 (obj):
const data = {arr: [1, 2, 3]};
const res = Object.values(data).flat().map(i => ++i);
console.log(res);
Data form 2 (array):
const data = [1, 2, 3];
const res = Object.values(data).flat().map(i => ++i);
console.log(res);
Do note, however, Object.values does not guarantee order, and thus your array may lose its order. Moreover, if you plan to use this in production .flat() isn't yet supported across all browsers and instead, you may consider looking at a polyfill option

Array.reduce() on an array of objects -- getting back strings of single letters

I'm working to understand Array.reduce() in JavaScript. I have an array of objects that I'm trying to apply .reduce() to, but I'm getting back an array of single letter strings.
Goal:
["Stuff", "necklace", "ring", "bracelet"]
Current Array of Objects
const productArray =
[
{
id: 1,
productTitle: "Necklace"
},
{
id: 2,
productTitle: "Ring"
},
{
id: 3,
productTitle: "Bracelet"
}
]
Function call
const newStuff = productArray.reduce(function(a, currentValue) {
return [...a, ...currentValue.productTitle];
}, ["Stuff"])
Actual result:
What do I need to do to specify that I don't want "productTitle" broken down into single-letter strings? I have been looking for resources regarding .reduce() on an array of objects but I haven't found anything very helpful. Any pointers?
To concatenate an array and value when using spread to create a new array, you spread the previous array to the new array, and add the new item without spreading it.
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.reduce((a, currentValue) =>
[...a, currentValue.productTitle], []);
console.log(newStuff);
In this case, it's better to use Array.map():
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.map((currentValue) => currentValue.productTitle);
console.log(newStuff);
Do not spread the title, pass it as it is:
const newStuff = productArray.reduce(function(a, currentValue) {
return [...a, currentValue.productTitle];
}, ["Stuff"]);
...currentValue.productTitle spreads into an array of individual letters, you only want to spread a variable, the aggregate here.
Basically a string is iterable, because the iterator is implemented and returns an array of single characters, if using spread syntax ....
Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
console.log([...'foo']);
Other answers have pointed out why your code is wrong. But I do want to also note that what you're doing is already covered by Array.prototype.concat:
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.reduce((a, val) => a.concat(val.productTitle), ['Struff']);
console.log(newStuff);
(And of course, as another answer has mentioned, this sounds more like a use for map than reduce, which might not matter since you're using this to learn reduce.)
The use of spread in this case is unnecessary and inefficient as it creates a new accumulator array from the previous one on every iteration. You can remove spread (and fix your issue) and use concat instead to keep it as a one-liner.
However, since you're just adding one new value on each iteration, you should use push. It requires one more line of code but is likely more efficient than using concat.
var productArray = [{id: 1,productTitle: "Necklace"},
{id: 2,productTitle: "Ring"},
{id: 3,productTitle: "Bracelet"}
];
// Using concat
var newStuff = productArray.reduce((acc, value) =>
acc.concat(value.productTitle),
["Stuff"]);
console.log(newStuff);
// Using push
var newStuff = productArray.reduce((acc, value) => {
acc.push(value.productTitle);
return acc;
}, ["Stuff"]);
console.log(newStuff);

Copy array N times to a flatted array

I've an array of four elements and I want to copy it to another array four times and I've done it by concatenating four times.
My efforts
let demoProperties = []
.concat(fourDemoProperties)
.concat(fourDemoProperties)
.concat(fourDemoProperties)
.concat(fourDemoProperties);
I also followed another way (map and reduce) but this way iterate two times.
Have there any easiest optimum way to copy N times? Any of your suggestions will be appreciated.
You can use the spread syntax:
const demoProperties = [...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties];
Or use Array#fill to duplicate the array, and then use spread syntax with Array#concat to get a new array:
const fourDemoProperties = [1, 2, 3, 4];
const demoProperties = [].concat(...Array(4).fill(fourDemoProperties));
console.log(demoProperties);
Note: both the manual an the Array#fill are shallow clones. If the items are objects, you'll clone the reference to the objects, and if you'll change one of them, the "copies" will change as well.
Example (check the browser's console):
const fourDemoProperties = [{ a: 1 }, { b: 2 }];
const demoProperties = [...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties];
demoProperties[0].a = 5000;
console.log(demoProperties);
How you do it depend if you want to keep the reference among the sub arrays or not.
var ar = [1,2,3,4],
ars = Array.from({length:4}).map(_ => ar),
brs = Array.from({length:4}).map(_ => ar.slice());
console.log(ars);
console.log(brs);

How should i get array of array in javascript as a single value array?

If a have an array in javascript like:
[[2,3,4],"data","payload",[name1,name2,name3]]
how should I get all the values as a single array like
Result array should be like this :
[2,3,4,"data","payload",name1,name2,name3]
You can flatten it with .concat().
var data = [[2,3,4],"data","payload",["name1","name2","name3"]];
console.log([].concat(...data));
Any Array argument passed to .concat() will be flattened into the result.
This also uses the "spread syntax", which is only available in newer engines. Use .apply() for legacy support.
var data = [[2,3,4],"data","payload",["name1","name2","name3"]];
console.log(data.concat.apply([], data));
Use reduce() for this.
const array = [[2,3,4],"data","payload",["name1","name2","name3"]]
const flattenedArray = array.reduce((a, b) => a.concat(b), [])
console.log(flattenedArray)
MDN reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
You could use concat() to concatenate all the items in your main array into one big array, which I understand is what you're after :
var my2dArray = [[2,3,4],"data","payload",[name1,name2,name3]];
var my1dArray = [];
for(var i = 0; i < my2dArray.length; i++)
{
my1dArray = my1dArray.concat(my2dArray[i]);
}
console.log(my1dArray); // will be [2,3,4,"data","payload",name1,name2,name3]
You can use the concat():
var array = [
[2, 3, 4],
"data",
"payload",
['name1', 'name2', 'name3'],
]
var newArr = [].concat.apply([], array);
console.log(newArr);

Categories

Resources