I'm trying to get the highest value of my object by ID and date. To explain better, this is my array:
[
{
"id":"6",
"date":"201901",
"value":"1"
},
{
"id":"6",
"date":"201901",
"value":"12"
},
{
"id":"6",
"date":"201901",
"value":"123"
},
{
"id":"6",
"date":"201901",
"value":"1231"
},
{
"id":"6",
"date":"201902",
"value":"4"
},
{
"id":"6",
"date":"201902",
"value":"45"
},
{
"id":"5",
"date":"201902",
"value":"56"
},
{
"id":"5",
"date":"201902",
"value":"46"
}
]
I'm trying to get this return (Filtering the highest value by id and date):
[
{
"id":"6",
"date":"201901",
"value":"1231"
},
{
"id":"6",
"date":"201902",
"value":"45"
},
{
"id":"5",
"date":"201902",
"value":"56"
}
]
In my code, I'm using map and filter but not works:
let resultados = array
array.map(item => {
resultados.filter(itemFilter => {
if(item.id == itemFilter.id && item.date == itemFilter.date){
if(itemFilter.value > item.value){
return itemFilter.value
}
}
})
})
An similar solutis is this
Someone can help me?
You could take a Map with a combined key of the wanted keys for grouping. Then take the greater value.
var data = [{ id: "6", date: "201901", value: "1" }, { id: "6", date: "201901", value: "12" }, { id: "6", date: "201901", value: "123" }, { id: "6", date: "201901", value: "1231" }, { id: "6", date: "201902", value: "4" }, { id: "6", date: "201902", value: "45" }, { id: "5", date: "201902", value: "56" }, { id: "5", date: "201902", value: "46" }],
result = Array.from(data
.reduce((m, o) => (key =>
!m.has(key) || m.get(key).value < o.value
? m.set(key, o)
: m
)(['id', 'date'].map(k => o[k]).join('|')), new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array.prototype.reduce :
yourArray.reduce( (accumulator, currentItem) => {
var previouslyGreatestItem = accumulator.find(item => item.id == currentItem.id && item.date == currentItem.date);
if (!previouslyGreatestItem) {
accumulator.push(currentItem);
} else if (previouslyGreatestItem.value < currentItem.value) {
previouslyGreatestItem.value = currentItem.value;
}
return accumulator;
}, []);
var yourArray = [{"id":"6","date":"201901","value":"1"},{"id":"6","date":"201901","value":"12"},{"id":"6","date":"201901","value":"123"},{"id":"6","date":"201901","value":"1231"},{"id":"6","date":"201902","value":"4"},{"id":"6","date":"201902","value":"45"},{"id":"5","date":"201902","value":"56"},{"id":"5","date":"201902","value":"46"}];
var result = yourArray.reduce( (accumulator, currentItem) => {
var previouslyGreatestItem = accumulator.find(item => item.id == currentItem.id && item.date == currentItem.date);
if (!previouslyGreatestItem) {
accumulator.push(currentItem);
} else if (previouslyGreatestItem.value < currentItem.value) {
previouslyGreatestItem.value = currentItem.value;
}
return accumulator;
}, []);
console.log(result);
Related
I am trying to achieve an operation where Ι am not sure where to start with.
Down below is my initial object:
[
{ type: "1", name: "Anthony" },
{
type: "1",
name: "Linus",
},
{
type: "2",
name: "Sebastin",
},
]
What I am trying to achieve is to move the objects which has same type inside an array and have a key value, named title and string type.
I am trying to produce an output equivalent to this and I am not sure where to begin with. Any help will be useful and appreciated. Thanks in advance <3
[
{
title: "1",
sub_items: [
{
type: "1",
name: "Anthony",
},
{
type: "1",
name: "Linus",
},
],
},
{
type: "2",
name: "Sebastin",
},
];
You can use Array.reduce() to group the input items by type/title and create the desired output:
const input = [{ "type":"1", "name":"Anthony" }, { "type": "1", "name": "Linus" }, { "type":"2", "name":"Sebastin" }]
const result = Object.values(input.reduce((acc, { type, name }) => {
acc[type] = acc[type] || { title: type, sub_items: [] };
acc[type].sub_items.push({ type, name });
return acc;
}, {}));
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
You can make it with Array.reduce
const data = [
{ type: "1", name: "Anthony" },
{
type: "1",
name: "Linus",
},
{
type: "2",
name: "Sebastin",
},
];
const output = data.reduce((acc, curr, index, list) => {
const matchNodes = list.filter((node) => node.type === curr.type);
if (matchNodes.length > 1) {
const accNode = acc.find((item) => item.title === curr.type);
if (accNode) {
accNode.sub_items.push(curr);
} else {
acc.push({
title: curr.type,
sub_items: [curr],
});
}
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(output);
Is there a way to compare these 2 objects based on topicID and items->item->id and return true for being same? (it must ignore unique element)
const var1 = [
{
unique: "8123456",
topicID: "1234",
items: {
item: [
{
id: "x",
},
{
id: "y",
},
],
},
},
{
unique: "123456",
topicID: "123",
items: {
item: [
{
id: "b",
},
{
id: "a",
},
],
},
},
];
const var2 = [
{
unique: "3123456",
topicID: "123",
items: {
item: [
{
id: "a",
},
{
id: "b",
},
],
},
},
{
unique: "2123456",
topicID: "1234",
items: {
item: [
{
id: "y",
},
{
id: "x",
},
],
},
},
];
a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]
function comparer(otherArray){
return function(current){
return otherArray.filter(function(other){
return other.value == current.value && other.display == current.display
}).length == 0;
}
}
var onlyInA = a.filter(comparer(b));
var onlyInB = b.filter(comparer(a));
result = onlyInA.concat(onlyInB);
console.log(result);
Here is put your required data and use this code you will get success
Try using:
const var1 = [
{
unique: "8123456",
topicID: "1234",
items: {
item: [
{
id: "x",
},
{
id: "y",
},
],
},
},
{
unique: "123456",
topicID: "123",
items: {
item: [
{
id: "b",
},
{
id: "a",
},
],
},
},
];
const var2 = [
{
unique: "3123456",
topicID: "123",
items: {
item: [
{
id: "a",
},
{
id: "b",
},
],
},
},
{
unique: "2123456",
topicID: "1234",
items: {
item: [
{
id: "y",
},
{
id: "x",
},
],
},
},
];
const var3 = [
{
unique: "8123456",
topicID: "1234",
items: {
item: [
{
id: "x",
},
{
id: "y",
},
],
},
},
{
unique: "123456",
topicID: "123",
items: {
item: [
{
id: "b",
},
{
id: "a",
},
],
},
},
];
function objCompare(object1, object2) {
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
const val1 = object1[key];
const val2 = object2[key];
const isObj= checkObj(val1) && checkObj(val2);
if (
isObj && !objCompare(val1, val2) ||
!isObj && val1 !== val2
) {
return false;
}
}
return true;
}
function checkObj(object) {
return object != null && typeof object === 'object';
}
console.log(objCompare(var1,var2));
console.log(objCompare(var1,var3));
Hope this helps !!!
Without knowing the exact use case, I'll outline a general idea of how you could go about it.
For each item in the array, generate a key based on the topicID and the concatenation of the id within items. From there, you construct a set of both lots of keys, then compare them. This would work assuming that:
There are no duplicates in a single array.
You only need to test for "equality". If you need to pull out the duplicated items it's more difficult, but the same approach can be followed.
const constructKey = o =>
`${o.topicID}_${o.items.item.map(item => item.id).join('')}`
const setEq = (a, b) => a.size === b.size && [...a].every(v => b.has(v));
const var1Keys = new Set(var1.map(constructKey));
const var2Keys = new Set(var2.map(constructKey));
console.log(setEq(var1Keys, var2Keys))
EDIT: Based on your comment, it seems as though you want to compare items regardless of order. Something like this:
const constructMap = (arr) =>
arr.reduce(
(map, { topicID, items }) =>
map.set(topicID, new Set(items.item.map(({ id }) => id))),
new Map(),
)
const setEq = (a, b) => a.size === b.size && [...a].every((v) => b.has(v))
const mapEq = (a, b) =>
a.size === b.size &&
[...a.entries()].every(([k, v]) => b.has(k) && setEq(v, b.get(k)))
const var1Map = constructMap(var1)
const var2Map = constructMap(var2)
console.log(mapEq(var1Map, var2Map))
I'm confused about array transform with reduce method. I can't figure out how to deal with nested object with literal keys.
To brings some advantage, I'll post some example I'm wrote and it work fine:
// consider flat array of objects
const names = [
{ name: "Jaden", sname: "Smith", age: 33 },
{ name: "Will", sname: "Smith", age: 12 },
{ name: "Jada", sname: "Smith", age: 29 },
{ name: "Jose", sname: "Varho", age: 21 },
{ name: "Josephina", sname: "Varho", age: 44 },
{ name: "Keanu ", sname: "Reeves", age: 44 }] ;
// suppose i need to transform that array to this shape:
/* {
"Smith": {
"Jaden": 33,
"Will": 12,
"Jada": 29
},
"Varho": {
"Jose": 21,
"Josephina": 44
},
"Reeves": {
"Keanu ": 44
}
}
*/
// this reducer do it's fine:
const shapeIt = (acc, item) => {
console.log('acc:', JSON.stringify(acc));
acc[item.sname] = { ...acc[item.sname], [item.name]: item.age }
return acc
}
const transformShape= (arr) => {
return arr.reduce((acc, item) => shapeIt(acc, item), {});
}
transformShape(names); //gives required shape
So now, let's imaging i have more complex array like:
const flatArray = [
{ "blockId": "first-block", "sectionId": "first-section", "fieldId": "_1", "value": "0" },
{ "blockId": "first-block", "sectionId": "first-section", "fieldId": "_2", "value": "1" },
{ "blockId": "first-block", "sectionId": "second-section", "fieldId": "_1", "value": "1" },
{ "blockId": "second-block", "sectionId": "first-section", "fieldId": "_1", "value": "1" },
{ "blockId": "second-block", "sectionId": "some-section", "fieldId": "_2", "value": "3" },
{ "blockId": "third-block", "sectionId": "other-section", "fieldId": "_1", "value": "3" }];
// and i strictly need to get this shape of object:
/* {
"first-block": {
"first-section": {
"_1": "0",
"_2": "1"
},
"second-section": {
"_1": "1"
}
},
"second-block": {
"first-section": {
"_1": "1"
},
"some-section": {
"_2": "3"
}
},
"third-block": {
"other-section": {
"_1": "3"
}
}
}
*/
At this moment I'm write this kind of reduce function. It works but it gives me only last fieldId keys of each section in block. if section in one block have more than one fieldId - it lose it. I'm watch for a accumulator, and see that only keys with different blockId, sectionId is accumulated, but not different fieldId's.
const shapeComplex = (acc, item) => {
console.log('acc:', JSON.stringify(acc));
acc[item.blockId] = { ...acc[item.blockId], [item.sectionId]: { [item.fieldId]: item.value } }
return acc
}
const transformComplex = (arr) => {
console.log('initialArr: ', arr)
return arr.reduce((acc, item) => shapeComplex(acc, item), {});
}
transformComplex(flatArray);
// it gives me shape with only last idField in same section and block:
/*
{
"first-block": {
"first-section": {
"_1": "0"
},
"second-section": {
"_1": "1"
}
},
"second-block": {
"first-section": {
"_1": "1"
},
"some-section": {
"_2": "3"
}
},
"third-block": {
"other-section": {
"_1": "3"
}
}
}
*/
Any help, please.
You could take an array of wanted keys for grouping and take either the value or a new object for the next level.
const
data = [{ blockId: "first-block", sectionId: "first-section", fieldId: "_1", value: "0" }, { blockId: "first-block", sectionId: "first-section", fieldId: "_2", value: "1" }, { blockId: "first-block", sectionId: "second-section", fieldId: "_1", value: "1" }, { blockId: "second-block", sectionId: "first-section", fieldId: "_1", value: "1" }, { blockId: "second-block", sectionId: "some-section", fieldId: "_2", value: "3" }, { blockId: "third-block", sectionId: "other-section", fieldId: "_1", value: "3" }],
keys = ['blockId', 'sectionId', 'fieldId'],
result = data.reduce((r, o) => {
keys.reduce(
(q, k, i, { length }) => q[o[k]] ??= i + 1 === length ? o.value : {},
r
);
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Approach by taking all values of the object and assign the last item as value for the most nested object.
This approach relies on the order of the values in each object.
const
data = [{ blockId: "first-block", sectionId: "first-section", fieldId: "_1", value: "0" }, { blockId: "first-block", sectionId: "first-section", fieldId: "_2", value: "1" }, { blockId: "first-block", sectionId: "second-section", fieldId: "_1", value: "1" }, { blockId: "second-block", sectionId: "first-section", fieldId: "_1", value: "1" }, { blockId: "second-block", sectionId: "some-section", fieldId: "_2", value: "3" }, { blockId: "third-block", sectionId: "other-section", fieldId: "_1", value: "3" }],
result = data.reduce((r, o) => {
const
values = Object.values(o),
value = values.pop();
values.reduce(
(q, k, i, { length }) => q[k] ??= i + 1 === length ? value : {},
r
);
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You also need to copy the properties (fields) of the innermost (section) object:
const shapeComplex = (acc, item) => {
console.log('acc:', JSON.stringify(acc));
acc[item.blockId] = {
...acc[item.blockId],
[item.sectionId]: {
...acc[item.blockId]?.[item.sectionId],
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[item.fieldId]: item.value
}
};
return acc
}
I would however recommend to either always use object spread on every level
const shapeComplex = (acc, item) => {
return {
...acc,
[item.blockId]: {
...acc[item.blockId],
[item.sectionId]: {
...acc[item.blockId]?.[item.sectionId],
[item.fieldId]: item.value
}
}
};
}
or to use mutations:
const shapeComplex = (acc, {blockId, sectionId, fieldId, value}) => {
const block = acc[blockId] ?? (acc[blockId] = {});
const section = block[sectionId] ?? (block[sectionId] = {});
section[fieldId] = value;
return acc;
}
As #Nina showed in here answer, you can generalise this to arbitrarily deep assignments.
You can do the following,
const flatArray = [
{ "blockId": "first-block", "sectionId": "first-section", "fieldId": "_1", "value": "0" },
{ "blockId": "first-block", "sectionId": "first-section", "fieldId": "_2", "value": "1" },
{ "blockId": "first-block", "sectionId": "second-section", "fieldId": "_1", "value": "1" },
{ "blockId": "second-block", "sectionId": "first-section", "fieldId": "_1", "value": "1" },
{ "blockId": "second-block", "sectionId": "some-section", "fieldId": "_2", "value": "3" },
{ "blockId": "third-block", "sectionId": "other-section", "fieldId": "_1", "value": "3" }];
const shapeComplex = (acc, item) => {
if(acc[item.blockId]) {
acc[item.blockId] = { ...acc[item.blockId], [item.sectionId]: {...acc[item.blockId][item.sectionId], [item.fieldId]: item.value } }
} else {
acc[item.blockId] = { ...acc[item.blockId], [item.sectionId]: {[item.fieldId]: item.value } }
}
return acc
}
const transformComplex = (arr) => {
return arr.reduce((acc, item) => shapeComplex(acc, item), {});
}
console.log(transformComplex(flatArray));
You are making a tree from a flat data structure. Specify the tree hierarchy (levels) and
properties to use to create a leaf node data element.
Example:
function treeFrom (arr, levels, name, value) {
return arr.reduce(
(root,item) =>
{
var node = root;
for (let level of levels) /* descend to bottom tier */
{
levelvalue = item[level];
if (! node[levelvalue]) node[levelvalue] = {};
node = node[levelvalue];
}
node[item[name]] = item[value];
return root;
}
,
{}
)
}
console.log ( treeFrom(flatArray, ['blockId', 'sectionId'], 'fieldId', 'value') );
I have the following data:
const data = [
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "Italy"
},
score: 5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "France"
},
score: 4.5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "UK"
},
score: 4.9
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Morocco"
},
score: 3.1
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Egypt"
},
score: 3.9
}
];
I want to group it based on the parent.id and calculate the average score, so I can have the following result:
[
{
parent: {
id: "1",
name: "Europe",
items: [
{
name: "Italy"
},
{
name: "France"
},
{
name: "UK"
}
],
score: 4.8
}
},
{
parent: {
id: "2",
name: "Afrique",
items: [
{
name: "Morocco"
},
{
name: "Egypt"
}
],
score: 3.5
}
}
]
I used the following function, but it doesn't work for the nested key, and also it's doesn't return the desired result schema.
let group = cars.reduce((r, a) => {
console.log("a", a);
console.log('r', r);
r[a.make] = [...r[a.parent.id] || [], a];
return r;
}, {});
console.log("group", group);
You can use _reduce() function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
var result = data.reduce((res, data) => {
if(!res[data.parent.id]) {
data.item = [data.item];
res[data.parent.id] = data;
} else {
res[data.parent.id]['item'].push(data['item']);
res[data.parent.id]['score'] = (res[data.parent.id]['score'] + data['score'])/2;
}
return res;
}, [])
.filter(x => x != null)
const data = [
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "Italy"
},
score: 5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "France"
},
score: 4.5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "UK"
},
score: 4.9
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Morocco"
},
score: 3.1
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Egypt"
},
score: 3.9
}
];
var result = data.reduce((res, data) => {
if(!res[data.parent.id]) {
data.item = [data.item];
res[data.parent.id] = data;
} else {
res[data.parent.id]['item'].push(data['item']);
res[data.parent.id]['score'] = (res[data.parent.id]['score'] + data['score'])/2;
}
return res;
}, [])
.filter(x => x != null)
console.log(result)
Create an object/hashmap, then format the resulting object into an array.
let continents = {}
data.forEach(function(country){
const continent_id = country.parent.id
let continent = continents[continent_id]
if(!continent){
continent = {
id: continent_id,
name: country.parent.name,
items: [],
}
continents[continent_id] = continent
}
continent.items.push({
name: country.item.name,
score: country.score
})
})
continents = Object.entries(continents).map(item => ({parent: item[1]}))
console.log(continents)
Output:
[
{
"parent":{
"id":"1",
"name":"Europe",
"items":[
{
"name":"Italy",
"score":5
},
{
"name":"France",
"score":4.5
},
{
"name":"UK",
"score":4.9
}
]
}
},
{
"parent":{
"id":"2",
"name":"Afrique",
"items":[
{
"name":"Morocco",
"score":3.1
},
{
"name":"Egypt",
"score":3.9
}
]
}
}
]
From the data you've provided if you additionaly need to count average of score property, use the following reduce method: it will iterate trough your data, group it and calculate total score value and count of score values. And after reduce groups object perform map that will calculate average for score for all the groups using totalScore and scoreCount
const data = [
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "Italy"
},
score: 5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "France"
},
score: 4.5
},
{
parent: {
id: "1",
name: "Europe"
},
item: {
name: "UK"
},
score: 4.9
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Morocco"
},
score: 3.1
},
{
parent: {
id: "2",
name: "Afrique"
},
item: {
name: "Egypt"
},
score: 3.9
}
];
let group = data.reduce((acc, rec) => {
if (acc.find(item => item.parent.id === rec.parent.id))
{
const idx = acc.findIndex(item => item.parent.id === rec.parent.id)
acc[idx].parent.items = acc[idx].parent.items.concat(rec.item)
acc[idx].parent.score += rec.score
acc[idx].parent.scoreCount +=1
} else {
acc = acc.concat({parent: {...rec.parent, score: rec.score, items: [rec.item], scoreCount:1}})
}
return acc
}, []).map(it => ({parent: {id: it.parent.id, name:it.parent.name, score: (it.parent.score / it.parent.scoreCount), items: it.parent.items}}));
console.log("group", group);
Sorry for the bad question title, couldn't figure a better one.
I have this array of options:
const options = [
{
display_name: "Size",
_id: "1",
values: [
{
label: "Small",
_id: "1"
},
{
label: "Extra Large",
_id: "2"
}
]
},
{
display_name: "Colors",
_id: "2",
values: [
{
label: "Red",
value: "#ff0000",
_id: "3"
},
{
label: "Green",
value: "#00ff21",
_id: "4"
},
]
}
];
I run this function against it to get Cartesian Product:
const getCartesian = object => {
return Object.entries(object).reduce(
(r, [key, value]) => {
let temp = [];
r.forEach(s =>
(Array.isArray(value) ? value : [value]).forEach(w =>
(w && typeof w === "object" ? getCartesian(w) : [w]).forEach(x =>
temp.push(Object.assign({}, s, { [key]: x }))
)
)
);
return temp;
},
[{}]
);
};
This will result in an array of objects in the following format (console.log output):
[{0: Object, 1: Object}, {0: Object, 1: Object}, ...]
The desired output is:
[
{
"option":{
"id":1,
"display_name":"Size"
},
"value":{
"label":"Small",
"id": 1
}
},
{
"option":{
"id":2,
"display_name":"Color",
},
"value":{
"id":5,
"label":"Red"
}
}
...
]
here's the playground and what I've tried so far: https://codesandbox.io/s/8nvwm76nnj
You need to map() at the end to convert array to object.
const options = [
{
display_name: "Size",
_id: "1",
values: [
{
label: "Small",
_id: "1"
},
{
label: "Extra Large",
_id: "2"
}
]
},
{
display_name: "Colors",
_id: "2",
values: [
{
label: "Red",
value: "#ff0000",
_id: "3"
},
{
label: "Green",
value: "#00ff21",
_id: "4"
},
]
}
];
const getCartesian = object => {
let t = Object.entries(object).reduce(
(r, [key, value]) => {
let temp = [];
r.forEach(s =>
(Array.isArray(value) ? value : [value]).forEach(w =>
(w && typeof w === "object" ? getCartesian(w) : [w]).forEach(x =>
temp.push(Object.assign({}, s, { [key]: x }))
)
)
);
return temp;
},
[{}]
);
return t.map(({0:val1,1:val2}) => ({option:val1,arr:val2}))
};
console.log(getCartesian(options));
You could wrap the array in an object with a property option. This gives you later an array with objects with option as key for the cartesian product.
const getCartesian = object => {
return Object.entries(object).reduce(
(r, [key, value]) => {
let temp = [];
r.forEach(s =>
(Array.isArray(value) ? value : [value]).forEach(w =>
(w && typeof w === "object" ? getCartesian(w) : [w]).forEach(x =>
temp.push(Object.assign({}, s, { [key]: x }))
)
)
);
return temp;
},
[{}]
);
};
const options = [{ display_name: "Size", _id: "1", values: [{ label: "Small", _id: "1" }, { label: "Extra Large", _id: "2" }] }, { display_name: "Colors", _id: "2", values: [{ label: "Red", value: "#ff0000", _id: "3" }, { label: "Green", value: "#00ff21", _id: "4" }] }];
console.log(getCartesian({ option: options }));
.as-console-wrapper { max-height: 100% !important; top: 0; }