How to create a new object from existing entries? - javascript

I am trying to create an object that will be filled with values from an existing object. In my case it should have as result per "Material" an object list with the "Code" and the "Quantity". In addition, if the "Material" and "Code" are the same, the "Quantity" should be summed up.
I hope that you can see from my example what I mean. Thanks
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}]
var arrResult = [{
"Material": "123",
"CodeQuantity": [{
"Code": "AAA",
"Quantity": 1
}, {
"Code": "BBB",
"Quantity": 4
}]
}, {
"Material": "456",
"CodeQuantity": [{
"Code": "CCC",
"Quantity": 7
}]
}]
console.log(arr)
console.log("Result:", arrResult)

An approach should consider breaking the OP's entire task into two separate ones.
Within an intermediate step one firstly does reduce the list of material items into a map of (grouped) material items.
The final step does a map-reduce on the values of the intermediate result, where the reduce task is responsible for summing up a material's Code specific Quantity value ...
function collectTotalCodeQuantity(index, item) {
const { Code, Quantity } = item;
// access or create the `Code` specific code quantity item.
const codeQuantityItem = (index[Code] ??= { Code, Quantity: 0 });
// sum up a `Code` specific code quantity item's quantity value.
codeQuantityItem.Quantity += Quantity;
return index;
}
function createMaterialGroup(index, item) {
const { Material: materialValue, ...rest } = item;
// create the `CodeQuantity` key in a more generic way from the
// `rest` object which is ... `item` data without `Material` property.
const compoundKey = Object.keys(rest).join('');
// access or create the `Material` specific group.
const group = index[materialValue] ??= { Material: materialValue };
// access or create the `CodeQuantity` specific list.
const list = group[compoundKey] ??= [];
// push the `rest` object into the `CodeQuantity` specific list.
list.push(rest);
return index;
}
const materialDataItemList = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "AAA",
"Quantity": 7
}];
const totalCodeQuantityItemList = Object
.values(
materialDataItemList.reduce(createMaterialGroup, {})
)
.map(materialGroup => {
materialGroup.CodeQuantity = Object.values(
materialGroup.CodeQuantity.reduce(collectTotalCodeQuantity, {})
);
return materialGroup;
});
console.log({ totalCodeQuantityItemList });
console.log(
'... intermediate process result ... map of (grouped) material items ...',
materialDataItemList.reduce(createMaterialGroup, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Edit
Moin! how can I add a new key "CodeQuantityGesamt" where the values of all "Quantity" of a "Material" is summed? example:
{
"Material": "123",
"CodeQuantityGesamt": 5,
"CodeQuantity": [{
"Code": "AAA",
"Quantity": 1
}, {
"Code": "BBB",
"Quantity": 4
}]
}
– InFlames82
This can be achieved by changing the mapping task from ...
.map(materialGroup => {
materialGroup.CodeQuantity = Object.values(
materialGroup.CodeQuantity.reduce(collectTotalCodeQuantity, {})
);
return materialGroup;
});
... to e.g. ...
.map(materialGroup => Object.assign(
materialGroup,
materialGroup.CodeQuantity.reduce(collectCodeQuantityTotals, {})
));
... together with adapting the implementation and changing the name of the former collectTotalCodeQuantity reducer function which becomes collectCodeQuantityTotals.
function collectCodeQuantityTotals(quantities, item, idx, arr) {
const { Code, Quantity } = item;
let {
CodeQuantityTotal = 0,
CodeQuantity = [],
index = {},
} = quantities;
// access ...
let codeQuantityItem = index[Code];
// ... or create the `Code` specific code quantity item.
if (!codeQuantityItem) {
codeQuantityItem = index[Code] = { Code, Quantity: 0 };
// push a newly created item into the CodeQuantity list.
CodeQuantity.push(codeQuantityItem);
}
// sum up a `Code` specific code quantity item's quantity value.
codeQuantityItem.Quantity += Quantity;
// sum up the total (or overall) code quantity value.
CodeQuantityTotal += Quantity;
// return a full collector/accumulator object as long as
// the reduce task takes place because `index` is needed
// as lookup, but return, as the final result, an object
// without the `index` property.
return (idx < arr.length - 1)
&& { CodeQuantityTotal, CodeQuantity, index }
|| { CodeQuantityTotal, CodeQuantity };
}
function createMaterialGroup(index, item) {
const { Material: materialValue, ...rest } = item;
// create the `CodeQuantity` key in a more generic way from the
// `rest` object which is ... `item` data without `Material` property.
const compoundKey = Object.keys(rest).join('');
// access or create the `Material` specific group.
const group = index[materialValue] ??= { Material: materialValue };
// access or create the `CodeQuantity` specific list.
const list = group[compoundKey] ??= [];
// push the `rest` object into the `CodeQuantity` specific list.
list.push(rest);
return index;
}
const materialDataItemList = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "AAA",
"Quantity": 7
}];
const totalCodeQuantityItemList = Object
.values(
materialDataItemList.reduce(createMaterialGroup, {})
)
.map(materialGroup => Object.assign(
materialGroup,
materialGroup.CodeQuantity.reduce(collectCodeQuantityTotals, {})
));
console.log({ totalCodeQuantityItemList });
console.log(
'... intermediate process result ... map of (grouped) material items ...',
materialDataItemList.reduce(createMaterialGroup, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Updated the solution to match your expectation.
This this. Hope it solves your use case.
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}]
var arrResultExpected = [{
"Material": "123",
"CodeQuantity": [{
"Code": "AAA",
"Quantity": 1
}, {
"Code": "BBB",
"Quantity": 4
}]
}, {
"Material": "456",
"CodeQuantity": [{
"Code": "CCC",
"Quantity": 7
}]
}]
//console.log(arr)
//console.log("ExpecredResult:", arrResultExpected)
const materialIds = arr.map(a => a.Material);
//console.log(materialIds);
const dedupedMaterialIds = [...new Set(materialIds)]
//console.log(dedupedMaterialIds);
const needArr = dedupedMaterialIds.map(entry => {
const matchingEntries = arr.filter(arrEntry => entry === arrEntry.Material);
//console.log(matchingEntries);
var summedResult = [];
matchingEntries.reduce(function(res, value) {
if (!res[value.Code]) {
res[value.Code] = {
Quantity: 0,
Code: value.Code
};
summedResult.push(res[value.Code])
}
res[value.Code].Quantity += value.Quantity
return res;
}, {});
//console.log(summedResult);
return {
Material: entry,
CodeQuantity: [...summedResult]
};
});
console.log(needArr);

try this
const arr = [{
"Material": "123",
"Code": "AAA",
"Quantity": 1
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "123",
"Code": "BBB",
"Quantity": 2
}, {
"Material": "456",
"Code": "CCC",
"Quantity": 7
}];
let group = arr.reduce((r, a) => {
r[a.Material] = [...r[a.Material] || [], a];
return r;
}, {});
var newArr = Object.keys(group).map(key => {
var elem = group[key];
var b = elem.map(e => {
return {
Code: e.Code,
Quantity: e.Quantity
}
});
var filteredArr = [];
b.map(i => {
var item = filteredArr.find(n => n.Code == i.Code);
if (item) {
item.Quantity += i.Quantity;
} else {
filteredArr.push(i);
}
})
return {
Material: key,
CodeQuantity: filteredArr
}
});
console.log(newArr);

Related

How to check an array of objects against another one?

Hi,
I have one array of objects with all items and their respective price like this:
var items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
];
then I have a client's car like this:
var cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
client's credit is stored in a variable. I want to check the second array against the first one to get the total of the cart and make sure it wont exceed client's credit. Im not sure how to do it though. I tried:
var mytotal=cart.map(d => {
var total=0;
items.forEach(rm => {
total = total+(d.qty*rm.price);
} return total;
});
if(credit >= total) {//dosomething}
but it didnt work. What is the right approach?
Thank you.
You can divide your problem into two tasks: join and sum.
Join
const joined = items.map(item => ({...item, ...cart.find(c => c.id === item.id)}));
Note that in case the id won't match, find will return null, and the spread (...) will result in no change to the object
Sum
const sum = joined.reduce((sum, curr) => sum += curr.price * curr.qty, 0);
A safer version would be:
const sum = joined.reduce((sum, curr) => sum += (curr.price ?? 0) * (curr.qty ?? 0), 0);
var items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
];
var cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
const joined = items.map(item => ({...item, ...cart.find(c => c.id === item.id)}));
const sum = joined.reduce((sum, curr) => sum += curr.price * curr.qty, 0);
console.log(`joined object is: `, joined);
console.log(`sum is: ${sum}`);
I am a little late in the game, but maybe the following snippet is still of interest? It picks up the idea of creating a lookup object itms and for each shopping cart entry it also combines two objects into a new one with a subtotal subt, so you can easliy create a meaningfull shopping cart table. The variable ttl is updated alongside and contains the total sum:
const items = [
{
"id": "001",
"name": "apple",
"price": 500
},
{
"id": "002",
"name": "banana",
"price": 700
},
{
"id": "003",
"name": "pear",
"price": 200
}
],
cart = [{
"id": "001",
"qty": 2
},
{
"id": "002",
"qty": 3
},
{
"id": "003",
"qty": 4
}
];
// Turn the items array into an object, facilitating a fast lookup:
const itms=items.reduce((a,c)=>(a[c.id]=c,a),{});
let ttl=0;
// calculate the totals:
const res=cart.map(c=>{
const p=itms[c.id], subt=c.qty*p.price;
ttl+=subt;
return {...c,...p,subt}
})
// Show the result:
console.log(res,ttl);
To implement a reusable and efficient solution you can create a lookup table on the items array, here using a Map, which allows you to directly access the item by id.
const itemLookup = new Map(items.map((item) => [item.id, item]))
// Map(3) {
// '001' => { id: '001', name: 'apple', price: 500 },
// '002' => { id: '002', name: 'banana', price: 700 },
// '003' => { id: '003', name: 'pear', price: 200 }
// }
You can then create a getCartTotal helper which will use the lookup table to total the cart passed to it. (Here we are assuming that any item that will be in the cart will also be in the items array, but for safety you could add optional chaining, t += (itemLookup.get(id)?.price ?? 0) * qty)
const getCartTotal = (cart) => {
return cart.reduce((t, { id, qty }) => (
t += itemLookup.get(id).price * qty
), 0);
}
The result allows you to efficiently re-sum the cart whenever it changes.
const items = [{ "id": "001", "name": "apple", "price": 500 }, { "id": "002", "name": "banana", "price": 700 }, { "id": "003", "name": "pear", "price": 200 }];
const itemLookup = new Map(items.map(({ id, ...item }) => [id, { id, ...item }]));
const getCartTotal = (cart) => {
return cart.reduce((total, { id, qty }) => (
total += itemLookup.get(id).price * qty
), 0);
}
const cart = [{ "id": "001", "qty": 2 }, { "id": "002", "qty": 3 }, { "id": "003", "qty": 4 }];
console.log(getCartTotal(cart)); // 3900
cart[0].qty += 2;
console.log(getCartTotal(cart)); // 4900
In your attempt, you're applying the map function to the cart array. Map applies the function to each element of the array, and returns the new array. The function total = 0 etc is being applied for each element separately.
In the map/reduce way of working, try getting the proper price of each cart element first with map, and then summarize using reduce.
Map/reduce is just one of many ways to solve this issue, you could also do it iteratively with a for loop like you were trying within your map function.

filtering an array: get max price and unique objects?

store = [{
"item": "shirt",
"price": 20
},
{
"item": "shirt",
"price": 50
},
{
"item": "pants",
"price": 10
},
{
"item": "pants",
"price": 20
}
]
//im filtering the array to get objects without duplication here
console.log(store.filter((v, i, a) => a.findIndex(v2 => ['item'].every(k => v2[k] === v[k])) === i))
and i would like to get the max price as well in the same filter so how would i get this output after excuting it ?
expected output:
[{
"item": "shirt",
"price": 50
},
{
"item": "pants",
"price": 20
}]
You could sort() them by price before filtering.
store = [{
"item": "shirt",
"price": 20
},
{
"item": "shirt",
"price": 50
},
{
"item": "pants",
"price": 10
},
{
"item": "pants",
"price": 20
}
]
const result = store.sort((a, b) => b.price - a.price).filter((v, i, a) => a.findIndex(v2 => ['item'].every(k => v2[k] === v[k])) === i);
console.log(result);
I like #axtck's answer. .... Having filtered the objects, now use .map() to find from the original data the max price by sorting:
.map(
({item,price}) =>
({item,price:store.filter(p => p.item === item).sort((a,b) => b.price - a.price)[0].price})
)
store = [{
"item": "shirt",
"price": 20
},
{
"item": "shirt",
"price": 50
},
{
"item": "pants",
"price": 10
},
{
"item": "pants",
"price": 20
}
]
//im filtering the array to get objects without duplication here
console.log(
store.filter((v, i, a) => a.findIndex(v2 => ['item'].every(k => v2[k] === v[k])) === i)
.map(
({item,price}) =>
({item,price:store.filter(p => p.item === item).sort((a,b) => b.price - a.price)[0].price})
)
)
You could use Array.reduce() to get the highest price for each item.
We'd enumerate through each value, creating a map object, and if no entry exists for that item or the existing entry has a lower price, we'd update:
const store = [{ "item": "shirt", "price": 20 }, { "item": "shirt", "price": 50 }, { "item": "pants", "price": 10 }, { "item": "pants", "price": 20 } ]
const result = Object.values(store.reduce((acc, { item, price }) => {
// Either item does not exist or has a lower price...
if (!acc[item] || acc[item].price < price) {
acc[item] = { item, price };
}
return acc;
}, {}))
console.log(result)
.as-console-wrapper { max-height: 100% !important; }

Check if array of objects, which also contain nested arrays with objects, are the same, if so, combine them into one object and add the keys together

I would need to check if the objects in the "food" array are equal to each other, and the ones that are - combine into one adding amount and mody.amount and leaving the rest unchanged. This is just for better order data displaying. I tried with lodash library and reduce but but I don't know exactly how to construct this function that nested objects(mody) adds values ​​as well, and in case isEqual returns false keep the object while concurrently concatenating the identical ones.
What I tried:
obj1.reduce((prev, next) => _.isEqual(prev, next) ? {...prev, amount: prev.amount + next.amount} : next
Now it looks like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
and would need something like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 2,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 2
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 2
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
The algorithm to sum the food amounts and mody amounts are almost the same, the difference is that for each food that has the same id we will sum the mody amount. To make the algorithm simpler I used a dictionary as the accumulator on the reduce function so we have a unique element per key. This element will be our final food or mody with the amount sum.
Mody sum algoritm:
const sumMody = (modyAccumulator, currentMody) => {
//Get the stored mody in the accumulator dictionary or null if it the mody is not stored
const storedMody = modyAccumulator[currentMody.id] ?? null
// if mody is null then add mody to the dictionary using its id as key
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
//Mody is stored then sum amount
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
The food sum algoritm is the same as the sumMody, the only difference is that it calls the sumMody function when the foods are equal:
const sumFood = (foodAccumulator, currentFood) => {
//Get the stored foodin the accumulator dictionary or null if it the food is not stored
const storedFood = foodAccumulator[currentFood.id] ?? null
// if food is null then add food to the dictionary using its id as key
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
//Food is stored then sum food amount
storedFood.amount += currentFood.amount
//Create a list with mody from both foods
const modyList = [...storedFood.mody, ...currentFood.mody]
//Use reduce passing the sumMody callback function and initialize the accumulator with a dictionary
const modySumDictionary = modyList.reduce(sumMody, {})
/* The function above return a dictionary where the identifier is the mody.id
and the value is the mody. We only need the values from that dictionary so
we use Object.values to extract all the values. */
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
To execute both sums:
//As explained before the reduce function will return a dictionary so we use Object.values to get only the values
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Algoritm without comments:
const sumMody = (modyAccumulator, currentMody) => {
const storedMody = modyAccumulator[currentMody.id] ?? null
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
const sumFood = (foodAccumulator, currentFood) => {
const storedFood = foodAccumulator[currentFood.id] ?? null
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
storedFood.amount += currentFood.amount
const modyList = [...storedFood.mody, ...currentFood.mody]
const modySumDictionary = modyList.reduce(sumMody, {})
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Reference to Object.values

Group an array of objects based on a specific field

I have an array of objects. I want to group them by a specific field.
[
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
]
The output I expect for grouping by name attribute is as follows.
{
// Group #1
"JOHN": [
{
"type": 2,
"sum": 200
}
{
"type": 1,
"sum": 5
}
],
// Group #2
"SERA":[
{
"type": 1,
"sum": 43
},
{
"type": 2,
"sum": 129
},
]
}
I used nested loops, but unfortunately the execution speed was slow and it did not give the right results.
As if you mentioned, we can use an object instead of an array for the most outer wrapper. And also swap inside one object to an array, then this is a possible solution.
var data = [{"name": "JOHN","type": 1,"sum": 5},{"name": "SERA","type": 1,"sum": 43},{"name": "SERA","type": 2,"sum": 129},{"name": "JOHN","type": 2,"sum": 200}];
var newData = {};
data.forEach( (item) => {
if (!(item['name'] in newData)) {
newData[item['name']] = [];
}
newData[item['name']].push(
{
'type': item['type'],
'sum' : item['sum']
}
);
});
console.log(newData);
Your proposed output structure is not valid, however using Array.reduce you can create an object in which all the properties are arrays of objects:
const data = [
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
];
const result = data.reduce((c, {name, type, sum}) => {
c[name] = c[name] || [];
c[name].push({type, sum});
return c;
}, {});
console.log(result);
One more way with forEach, destructuring and ?? operator
const merge = (arr) => {
const obj = {};
arr.forEach(({ name, ...rest }) => (obj[name] ??= []).push(rest));
return obj;
};
const data = [
{
name: "JOHN",
type: 1,
sum: 5,
},
{
name: "SERA",
type: 1,
sum: 43,
},
{
name: "SERA",
type: 2,
sum: 129,
},
{
name: "JOHN",
type: 2,
sum: 200,
},
];
console.log(merge(data));
You can use this function which take advantage of Array.prototype.reduce to transform the initial data to another structure of array.
let data = [
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
];
function groupedBy(data, field) {
let fieldValues = [...data].reduce((acc, current) => {
return acc.concat(current[field]);
}, []).filter((value, index, self) => {
return self.indexOf(value) === index;
});
let results = fieldValues.reduce((acc, item) => {
let items = [...data].filter(el => {
return el.name === item;
});
items.forEach(i => delete i.name);
return Object.assign(acc, { [item]: items});
}, {});
return results;
}
console.log(groupedBy(data, "name"));

How to merge multiple object arrays into one array cross with sub array?

I have two arrays of objects:
1)
[
{
"userId": 9
},
{
"userId": 14
}
]
2)
[{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
I would like to merge two arrays as follows:
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
I tried to use let however I couldn't find the way to manipulate switch the subarray :
let arr1 = [{"userId": 9}, {"userId": 14}];
let arr2 = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}];
let result = arr1.map(o => Object.assign(o, ...arr2));
console.log(result);
return result;
The result I got with the previous implementation is like this :
[{"userId":9,"role":"1","group":"2"},{"userId":14,"role":"1","group":"2"}]
However, I would like to get the result as follows :
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
var a = [{
"userId": 9
},
{
"userId": 14
}
]
var b = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}]
console.log(
b.map(z=>a.map(x=>({...x, ...z}))).flat()
)
Another solution using for loop
let arr1 = [{ "userId": 9 }, { "userId": 14 }]
let arr2 = [{"role": "1","group": "3"}, {"role": "1","group": "2" }]
let result = [];
for (let group of arr2) {
for (let user of arr1) [
result.push(Object.assign({}, group, user))
]
}
console.log(JSON.stringify(result))
//output is:
// [
// {"role":"1","group":"3","userId":9},
// {"role":"1","group":"3","userId":14},
// {"role":"1","group":"2","userId":9},
// {"role":"1","group":"2","userId":14}
// ]
Stackblitz example
To achieve expected result, use below option of looping through two arrays
var x = [
{
"userId": 9
},
{
"userId": 14
}
]
var y = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
let result = []
y.forEach((v, i) =>{
x.forEach((y,i) => result.push({...v, ...y}))
})
console.log(result);
codepen - https://codepen.io/nagasai/pen/pxvzOG?editors=1010
You could iterate over the two arrays like this and push the merged values into result:
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
Which could also be written in ONE LINE:
arr1.forEach(e => arr2.forEach(e2 => result.push(Object.assign({}, e, e2))));
const arr1 = [{
"userId": 9
},
{
"userId": 14
}
];
const arr2 = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
const result = [];
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
console.log(result);
You can use a mix a reduce and map to boil it down to a single array of objects.
let data = [{
"userId": 9
},
{
"userId": 14
}
]
let metaData = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
let dataReducer = data.reduce((acc, curr) => {
let metadataReducer = metaData.map((val) => {
return {
...curr,
...val
};
}, []);
return [...acc, ...metadataReducer];
}, []);
console.log(dataReducer)
Here a short approach for an arbitrary count of arrays of objects.
var array1 = [{ userId: 9 }, { userId: 14 }],
array2 = [{ role: "1", group: "3" }, { role: "1", group: "2" }],
result = [array1, array2]
.reduce((a, b) =>
a.reduce((r, v) =>
r.concat(b.map(w => Object.assign({}, v, w))), []));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're basically asking for a Cartesian product of the two arrays. flatMap is a useful function here. For each element of one array, merge it with all objects from the other array, then return a flat result.
const a = [{userId: 9}, {userId: 14}];
const b = [{role: "1", group: "3"}, {role: "1", group: "2"}];
const merged = b.flatMap(ae => a.map(be => ({...be, ...ae})));
console.log(merged);

Categories