Union arrays from all object properties - javascript

Lets say I have an object:
let obj={
hash1:{
images:[img1,img2....]
}
hash2:{
images:[img100,img200....]
}
hash3:{
images:[img1000,img2000....]
}
...
}
I want to union all those arrays in one array.
I understand that I can use next code:
let unionArray=[];
Object.values(obj).forEach((item)=>{
unionArray=unionArray.concat(item.images)
});
Are there more elegant way to do such task e.g with some framework or in one line coding.

An array reduction will do pretty nicely here:
let union = Object.values(obj).reduce((c, i) => c.concat(i.images), []);

You can use map() on Object.keys() and ES6 spread syntax.
let obj = {"hash1":{"images":["img1","img2"]},"hash2":{"images":["img100","img200"]},"hash3":{"images":["img1000","img2000"]}}
var arr = [].concat(...Object.keys(obj).map(e => obj[e].images));
console.log(arr)

Either use Array#map.
const union = [].concat(...Object.values(obj).map(v => v.images));

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 or Query - Convert Associative Array into Object

This is a simple question, not an expert in JS by any means and searched around but couldn't get any existing examples on Stackoverflow to work.
Basically I have a associative array and I need to convert it into an object:
Example:
var combinedproducts = [["Testing-1","test-1"],["Testing-2","test2"],["Testing-3","test3"]]
Need it to become this:
var products = {
// 'productid1':'Product Description One',
'Testing-1':'test-1',
'Testing-2':'test-2',
'Testing-3':'test-3'
};
What's the best / simplest way to do this? I can use regular javascript or jquery.
Thanks for the help!
If you don't have particular support issues, you can simply use Object.fromEntries, assuming "test2" and "test3" are actually array typos rather than intended to be transformed to test-2 and test-3 respectively as in your sample output.
Otherwise, you need to apply transformation to them (in that case, either reduce, a simple for or a foreach or even map can accomplish that).
Beware that, as mentioned above, Object.entries has not the same support as other solutions. For instance, keep in mind that it WON'T work in IE and Edge in general, check this link for further compatibility informations.
var combinedproducts = [["Testing-1","test-1"],["Testing-2","test2"],["Testing-3","test3"]];
const products = Object.fromEntries(combinedproducts);
console.log(products);
You can do it with .reduce() on your source array:
let object = combinedProducts.reduce((o, a) => (
o[a[0]] = a[1],
o
), {});
For what it's worth, the source array isn't really an "associative array" in any formal sense. JavaScript doesn't have an associative array type.
You can use array reduce. Inside the callback function add the first element of the inner array as key and the second element as the value
let data = [
["Testing-1", "test-1"],
["Testing-2", "test2"],
["Testing-3", "test3"]
];
let newData = data.reduce((acc, curr) => {
acc[curr[0]] = curr[1]
return acc;
}, {});
console.log(newData)
you can also use this method
const c = [["Testing-1","test-1"],["Testing-2","test2"],["Testing-3","test3"]];
obj = c.reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }), {});
console.log(obj)
One more alternate way doing in one line with Object.assign and map.
var combinedproducts = [
["Testing-1", "test-1"],
["Testing-2", "test2"],
["Testing-3", "test3"]
];
const obj = Object.assign(
{},
...combinedproducts.map(([key, value]) => ({ [key]: value }))
);
console.log(obj);

ES6 Merge two arrays (array contains another array inside) based on key Typescript or Javascript

I want to merge two arrays both array contains another array inside. refer below two arrays.
const arr1=
[{"projectId":30278,"projectName":null,"details":[{"amount":"9097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"}]},{"projectId":37602,"projectName":null,"details":[{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"}]}]
const arr2=
[{"projectId":30278,"projectName":null,"details":[{"amount":"8097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"}]},{"projectId":37602,"projectName":null,"details":[{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"}]}]
when i used ES6 spread operator, both values are appended to single array. But I want to merge based upon prjectId in that array.
So after merge, i need to get the result like below
const result =
[{"projectId":30278,"projectName":null,"details":[{"amount":"9097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"},
{"amount":"8097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"}
]},
{"projectId":37602,"projectName":null,"details":[{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"},
{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"}
]}]
const arr1=
[{"projectId":30278,"projectName":null,"details":[{"amount":"9097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"}]},{"projectId":37602,"projectName":null,"details":[{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"8234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"}]}]
const arr2=
[{"projectId":30278,"projectName":null,"details":[{"amount":"8097457.11","currency":"USD","paymentDate":"2016-05-16T00:00:00"}]},{"projectId":37602,"projectName":null,"details":[{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-30T00:00:00"},{"amount":"7234743.0","currency":"USD","paymentDate":"2019-04-23T00:00:00"}]}]
var fullArray = [...arr1,...arr2];
var mergedData ={};
fullArray.forEach(function(data){
if(mergedData[data.projectId]){
mergedData[data.projectId]["details"] = mergedData[data.projectId]["details"].concat(data.details)
} else {
mergedData[data.projectId] = data;
}
})
console.log(Object.values(mergedData))
You can easily achieve that using Lodash unionBy function.
const result = _.unionBy(arr1, arr2, 'projectId')
You can also try this in this case scenario.
let mergedArr = [];
let projectIdsArr1 = arr1.map(item => item.projectId);
arr2.map(outerLoopItem => {
if (projectIdsArr1.includes(outerLoopItem.projectId)) {
let found = arr1.find(innerLoopItem => innerLoopItem.projectId === outerLoopItem.projectId);
found.details = [...found.details, ...outerLoopItem.details];
mergedArr.push(found);
} else mergedArr.push(outerLoopItem);
});
console.log(mergedArr);

Can I declare an array of values that are nested inside a collection of objects without writing a loop?

Maybe a spread operator or destructuring instead?
Instead of writing this function and calling it with the collection to create an array
function namesArray(group) {
let names = [];
group.values.forEach( (value) => {
names.push(value.name);
});
return names;
}
names: Array<string> = namesArray(group);
I want to do something like this:
names: Array<string> = group.values[....].value.name;
with the ellipsis representing some kind of operator.
You're looking for map():
const names = group.values.map(v => v.name);
Use the combination of map and arrow functions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

es6 unique array of objects with set

I came across this example for creating unique arrays with es6
[ ...new Set(array) ]
Which seems to work fine until I tried it with an array of objects and it didn't return unique array.
i.e.
let item = [ ...new Set([{id:123,value:'test'},{id:123,value:'test'}]) ];
Why is that ?
you can try to do
uniqueArray = a => [...new Set(a.map(o => JSON.stringify(o)))].map(s => JSON.parse(s))
I know its ugly as hell but in most cases works apart from where you have new Date() in your object param then that on stringify be converted to ISO string.
so then do
let arr = [{id:1},{id:1},{id:2}];
uniqueArray(arr) //[{id:1},{id:2}]
Why is that ?
As per documentation
The Set object lets you store unique values of any type, whether
primitive values or object references.
Now reference for each of those arrays inside that Set constructor will be different so they are not considered to be a unique value by the constructor.
This will work:
let objectReference = {id:123,value:'test'}
let uniqueArray = [...new Set([objectReference, objectReference])]
>> [{id:123,value:'test'}]
What you're doing:
let objRef1 = {id:123,value:'test'} // creates a reference to a location in memory
let objRef2 = {id:123,value:'test'} // creates a new reference to a different place in memory
let uniqueArray = [...new Set([objRef1, objRef2])]
>> [{id:123,value:'test'},{id:123,value:'test'}]

Categories

Resources