Match element with array of object and push to new Array - javascript

Suppose I have an array of object as,
const attachmentData = [{name: 'Suman Baidh',attachment: ["123","456"]},
{name: 'John Sigma',attachment: ["789","101112]},
{name: 'Binay', attachment: ["131415","161718","192021]}]
And another array of object as,
const attachmentDetail = [{"id":"123",details:{"cost":10,"quantity":20}},
{"id":"456",details: {"cost":15,"quantity":28}},
{"id":"789",details:{"cost":4,"quantity":9}},
{"id":"101112",details:{"cost":40,"quantity":2}},
{"id":"131415",details:{"cost":12,"quantity":9}},
{"id":"161718",details:{"cost":45,"quantity":2}},
{"id":"192021",details:{"cost":120,"quantity":1}}]
I want the O/P as: Such that the id which is matched with attachmentDetail also has name along with it and pushed to new array.
[{"name":"Suman Baidh","id":"123","cost":10,"quantity":20},
{"name":"Suman Baidh","id":"456","cost":15,"quantity":28},
{"name":"John Sigma","id":"789","cost":4,"quantity":9} ,
{"name":"John Sigma","id":"101112","cost":40,"quantity":2},
{"name":"Binay","id":"131415","cost":12,"quantity":9},
{"name":"Binay","id":"161718","cost":45,"quantity":2},
{"name":"Binay","id":"192021","cost":120,"quantity":1}]
For this I tried as,
let newArray = []
for(let i = 0;i<attachmentData.length;i++)}{
for(let j = 0;j<attachmentData[i].attachment.length;j++){
if(attachmentData[i].attachment[j] == attachmentDetail.id){
newArray.push(...attachmentData[i], ... attachmentData[i].attachment[j]
}
}
}
On console.log(newArray) , its giving me not the answer I wanted.
If anyone needs any further information, please let me know. Any suggestion would be really helpful.

Try this,
const attachmentData = [
{ name: "Suman Baidh", attachment: ["123", "456"] },
{ name: "John Sigma", attachment: ["789", "101112"] },
{ name: "Binay", attachment: ["131415", "161718", "192021"] },
];
const attachmentDetail = [
{ id: "123", details: { cost: 10, quantity: 20 } },
{ id: "456", details: { cost: 15, quantity: 28 } },
{ id: "789", details: { cost: 4, quantity: 9 } },
{ id: "101112", details: { cost: 40, quantity: 2 } },
{ id: "131415", details: { cost: 12, quantity: 9 } },
{ id: "161718", details: { cost: 45, quantity: 2 } },
{ id: "192021", details: { cost: 120, quantity: 1 } },
];
let newArr = [];
attachmentData.forEach(({name, attachment}) => {
attachment.forEach((id) => {
const { details: { cost, quantity } } = attachmentDetail.find((item) => item.id === id)
newArr.push({ name, id, cost, quantity})
})
})
console.log(newArr)
NOTE: Try to use find, map, forEach, filter functions to simplify the for loop whenever possible.

The problem is in the line:
if (attachmentData[i].attachment[j] === attachmentDetail.id) {
Here attachmentDetail is an array. To access its element you need to use attachmentDetail[index].id.
You will need to loop through it to match the id from attachmentData.

const attachmentData = [{name: 'Suman Baidh', attachment: ["123", "456"]},
{name: 'John Sigma', attachment: ["789", "101112"]},
{name: 'Binay', attachment: ["131415", "161718", "192021"]}];
const attachmentDetail = [{"id": "123", details: {"cost": 10, "quantity": 20}},
{"id": "456", details: {"cost": 15, "quantity": 28}},
{"id": "789", details: {"cost": 4, "quantity": 9}},
{"id": "101112", details: {"cost": 40, "quantity": 2}},
{"id": "131415", details: {"cost": 12, "quantity": 9}},
{"id": "161718", details: {"cost": 45, "quantity": 2}},
{"id": "192021", details: {"cost": 120, "quantity": 1}}];
let newArray = []
for (let i = 0; i < attachmentData.length; i++) {
for (let j = 0; j < attachmentData[i].attachment.length; j++) {
for (let k = 0; k < attachmentDetail.length; ++k) {
if (attachmentData[i].attachment[j] === attachmentDetail[k].id) {
newArray.push({
name: attachmentData[i].name,
id: attachmentDetail[k].id,
...attachmentDetail[k].details
});
}
}
}
}
console.log(newArray);
Or
const attachmentData = [{name: 'Suman Baidh', attachment: ["123", "456"]},
{name: 'John Sigma', attachment: ["789", "101112"]},
{name: 'Binay', attachment: ["131415", "161718", "192021"]}];
const attachmentDetail = [{"id": "123", details: {"cost": 10, "quantity": 20}},
{"id": "456", details: {"cost": 15, "quantity": 28}},
{"id": "789", details: {"cost": 4, "quantity": 9}},
{"id": "101112", details: {"cost": 40, "quantity": 2}},
{"id": "131415", details: {"cost": 12, "quantity": 9}},
{"id": "161718", details: {"cost": 45, "quantity": 2}},
{"id": "192021", details: {"cost": 120, "quantity": 1}}];
const newArray = attachmentDetail.map(x => ({
name: attachmentData.filter(y => y.attachment.includes(x.id))[0].name,
id: x.id, ...x.details
}));
console.log(newArray);
Output
[
{ name: 'Suman Baidh', id: '123', cost: 10, quantity: 20 },
{ name: 'Suman Baidh', id: '456', cost: 15, quantity: 28 },
{ name: 'John Sigma', id: '789', cost: 4, quantity: 9 },
{ name: 'John Sigma', id: '101112', cost: 40, quantity: 2 },
{ name: 'Binay', id: '131415', cost: 12, quantity: 9 },
{ name: 'Binay', id: '161718', cost: 45, quantity: 2 },
{ name: 'Binay', id: '192021', cost: 120, quantity: 1 }
]

I think that something like this will work!
const attachmentData = [
{ name: "Suman Baidh", attachment: ["123", "456"] },
{ name: "John Sigma", attachment: ["789", "101112"] },
{ name: "Binay", attachment: ["131415", "161718", "192021"] },
];
const attachmentDetail = [
{ id: "123", details: { cost: 10, quantity: 20 } },
{ id: "456", details: { cost: 15, quantity: 28 } },
{ id: "789", details: { cost: 4, quantity: 9 } },
{ id: "101112", details: { cost: 40, quantity: 2 } },
{ id: "131415", details: { cost: 12, quantity: 9 } },
{ id: "161718", details: { cost: 45, quantity: 2 } },
{ id: "192021", details: { cost: 120, quantity: 1 } },
];
const newArray = attachmentDetail.map((detail) => {
const data = attachmentData.find((data) => data.attachment.includes(detail.id));
return {name: data.name, id: detail.id, ...detail.details}
})

If we want to deal with two arrays(specially for large sets of data), It's always good to convert one array to object(hash) and iterate over the other to find the matching.
const attachmentData = [{name: 'Suman Baidh',attachment: ["123","456"]}, {name: 'John Sigma',attachment: ["789","101112"]}, {name: 'Binay', attachment: ["131415","161718","192021"]}]
const attachmentDetail = [{"id":"123",details:{"cost":10,"quantity":20}}, {"id":"456",details: {"cost":15,"quantity":28}}, {"id":"789",details:{"cost":4,"quantity":9}}, {"id":"101112",details:{"cost":40,"quantity":2}}, {"id":"131415",details:{"cost":12,"quantity":9}}, {"id":"161718",details:{"cost":45,"quantity":2}}, {"id":"192021",details:{"cost":120,"quantity":1}}];
function customMerge(data, attachments) {
const hashById = attachments.reduce((acc, ele) => {
acc[ele.id] = ele;
return acc;
}, {});
return data.reduce((acc, {attachment, name}) => {
return acc.concat(attachment.map(id => ({name, id, details: hashById[id].details})));
},[]);
}
console.log(customMerge(attachmentData, attachmentDetail))

const attachmentData = [
{ name: 'Suman Baidh', attachment: [ '123', '456' ] },
{ name: 'John Sigma', attachment: [ '789', '101112' ] },
{ name: 'Binay', attachment: [ '131415', '161718', '192021' ] },
];
const attachmentDetail = [
{ id: '123', details: { cost: 10, quantity: 20 } },
{ id: '456', details: { cost: 15, quantity: 28 } },
{ id: '789', details: { cost: 4, quantity: 9 } },
{ id: '101112', details: { cost: 40, quantity: 2 } },
{ id: '131415', details: { cost: 12, quantity: 9 } },
{ id: '161718', details: { cost: 45, quantity: 2 } },
{ id: '192021', details: { cost: 120, quantity: 1 } },
];
const newArray = [];
for (let i = 0; i < attachmentData.length; i++) {
const { attachment } = attachmentData[i];
for (let j = 0; j < attachment.length; j++) {
attachmentDetail.some(element => {
if (element.id === attachment[j]) {
newArray.push({ name: attachmentData[i].name, ...element });
return true;
}
});
}
}
console.log(newArray);

You can first create a Map whose keys are the attachment ids and value is the name corresponding to that attachment.
Then loop over attachmentDetail array and just add the name using the Map created.
const
attachmentData = [{ name: "Suman Baidh", attachment: ["123", "456"] }, { name: "John Sigma", attachment: ["789", "101112"] }, { name: "Binay", attachment: ["131415", "161718", "192021"] }],
attachmentDetail = [{ id: "123", details: { cost: 10, quantity: 20 } }, { id: "456", details: { cost: 15, quantity: 28 } }, { id: "789", details: { cost: 4, quantity: 9 } }, { id: "101112", details: { cost: 40, quantity: 2 } }, { id: "131415", details: { cost: 12, quantity: 9 } }, { id: "161718", details: { cost: 45, quantity: 2 } }, { id: "192021", details: { cost: 120, quantity: 1 } }],
map = attachmentData.reduce((m, o) => (o.attachment.map((a) => m.set(a, o.name)), m), new Map()),
res = attachmentDetail.map(({ id, details }) => (name => ({ id, name, ...details }))(map.get(id)));
console.log(res);

Related

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1

How can I get the result from arr1 and arr2, When the ID matches I need to copy the content from arr1
const arr1 = [
{ id: 1, name: "omar" },
{ id: 2, name: "laith" },
{ id: 3, name: "aref" },
]
const arr2 = [
{ id: 1, rating: "good" },
{ id: 2, rating: "very good" },
{ id: 2, rating: "very good" },
{ id: 3, rating: "Excellence" },
{ id: 3, rating: "Excellence" },
]
//expected output
const result = [
{ id: 1, rating: "good", name: "omar" },
{ id: 1, rating: "good", name: "omar" },
{ id: 2, rating: "very good", name: "laith" },
{ id: 3, rating: "Excellence", name: "aref" },
{ id: 3, rating: "Excellence", name: "aref" },
]
use reduce with filter
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
const result = arr1.reduce((acc,item) => {
const list = arr2.filter(i => i.id === item.id)
return [...acc, ...list.map(i => ({id: i.id,rating:i.rating, name: item.name}))]
}, [])
console.log(result)
Basically with a loop. Actually 2. Using a temporary object (result) as dictionary (or map) we can make it efficient searching for a match to each id. This is of complexity O(n) basically.
const arr1 = [ { id: 1, name: "omar" }, { id: 2, name: "laith" }, { id: 3, name: "aref" }, ];
const arr2 = [ { id: 1, rating: "good" }, { id: 2, rating: "very good" }, { id: 2, rating: "very good" }, { id: 3, rating: "Excellence" }, { id: 3, rating: "Excellence" }, ];
var result = {}
arr1.forEach(function(item1) {
result[item1.id] = item1;
});
arr2.forEach(function(item2) {
result[item2.id] = (result[item2.id] || item2)
result[item2.id]['rating'] = item2.rating
})
result = Object.values(result)
console.log(result)

How to the get the sum of all the field with the same name in a nested array?

I'm trying to find the sum of all the field values of the nested array, I suck at explaining stuffs like this, I hope the code below will give you some insight of what I want to do.
The array looks like this
data = [
{
id: 8434,
name: listName,
data: [
{name: "a name",
quantity: 20,
}
{name: "another name",
quantity: 40,
}
{name: "another new name",
quantity: 40,
}
]
},
{
id: 54343,
name: "new list name",
data: [
{name: "a name",
quantity: 12,
}
{name: "another name",
quantity: 10,
}
{name: "another new name",
quantity: 16,
}
]
}
]
This is how I want the data to be after carrying out the sum
transformed = [
{name: "a name", quantity: 32},
{name: "another name", quantity: 50},
{name: "another new name", quantity: 56}
]
You can use Array.flatMap() followed by Array.reduce() to get the desired result.
We start by calling .flatMap() to get all the data values, then calling .reduce() on these to sum each value by name.
This will create an object, with a property for each name, we then call Object.values() to return to an array.
const data = [ { id: 8434, name: 'listName', data: [ { name: "a name", quantity: 20, }, { name: "another name", quantity: 40, }, { name: "another new name", quantity: 40, } ] }, { id: 54343, name: "new list name", data: [ { name: "a name", quantity: 12, }, { name: "another name", quantity: 10, }, { name: "another new name", quantity: 16, } ] } ];
const transformed = Object.values(data.flatMap(({ data }) => data).reduce((acc, { name , quantity }) => {
acc[name] = acc[name] || { name, quantity: 0 };
acc[name].quantity += quantity;
return acc;
}, {}))
console.log('Transformed:', transformed)
.as-console-wrapper { max-height: 100% !important; }
just loop them through and create a new object..
const data = [
{
id: 8434,
name: 'listName',
data: [
{
name: "a name",
quantity: 20,
},
{
name: "another name",
quantity: 40,
},
{
name: "another new name",
quantity: 40,
}
]
},
{
id: 54343,
name: "new list name",
data: [
{
name: "a name",
quantity: 12,
},
{
name: "another name",
quantity: 10,
},
{
name: "another new name",
quantity: 16,
}
]
}
]
// Logic:
const transformed = []
data.forEach(d => {
d.data.forEach(item => {
const exist = transformed.find(t => t.name == item.name)
if(exist)
exist.quantity += item.quantity
else
transformed.push(item)
})
})
console.log(transformed)
Output:
[
{ name: 'a name', quantity: 32 },
{ name: 'another name', quantity: 50 },
{ name: 'another new name', quantity: 56 }
]
const transform = (data) => {
const quantitySum = new Map()
data.forEach(list => {
list.data.forEach(({ name, quantity }) => {
if (quantitySum.has(name)) {
quantitySum.set(name, quantitySum.get(name) + quantity)
} else {
quantitySum.set(name, quantity)
}
})
})
return Array.from(quantitySum.entries())
.map(([name, sum]) => ({
name,
quantity: sum
}))
}

Get quantity in object respective with the category

I want the result to sum all the quantity of same cat.
var data = [
{ cat: 'EK-1',name:"test",info:"mat", quantity: 3},
{ cat: 'EK-2', name:"test2",info:"nat"quantity: 1}
];
I have array of object having some similar objects. How to add quantity and create unique object? This is what I tried.
var data = [{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-2',
name: "test2",
info: "nat",
quantity: 1
}
];
const products = Array.from(data.reduce((acc, {
cat,
quantity
}) =>
acc.set(cat, (acc.get(cat) || 0) + quantity),
new Map()
), ([cat, quantity]) => ({
cat,
quantitya
}));
console.log(products);
You first group and sum quantities under categories keys, using reduce and then you discard those keys with Object.values.
var data = [{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-1',
name: "test",
info: "mat",
quantity: 1
},
{
cat: 'EK-2',
name: "test2",
info: "nat",
quantity: 1
}];
const result = Object.values(data.reduce((acc, item) => {
if (!acc[item.cat]) {
acc[item.cat] = item;
} else {
acc[item.cat] = { ...item, quantity: item.quantity + acc[item.cat].quantity }
}
return acc;
}, {}))
console.log(result)
You could get the complete object as value for the map and increment quantity.
const
data = [{ cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-1', name: "test", info: "mat", quantity: 1 }, { cat: 'EK-2', name: "test2", info: "nat", quantity: 1 }],
products = Array.from(
data
.reduce(
(acc, o) => acc.set(o.cat, { ...o, quantity: (acc.get(o.cat)?.quantity || 0) + o.quantity }),
new Map
)
.values()
);
console.log(products);
.as-console-wrapper { max-height: 100% !important; top: 0; }

pushing a string into array return a number and not the actual string?

I am trying pushing the name but in the console log I see just a number and not the actual name
What am i doing wrong??
const cartItems = [{
id: 1,
name: "Soup",
price: 3,
category: "starters",
count: 1
},
{
id: 2,
name: "Pâté",
price: 5,
category: "starters",
count: 1
},
{
id: 9,
name: "Sticky toffee",
price: 18,
category: "desserts",
count: 1
}
]
var dishesArray = [];
var groupByCategory = []
cartItems.reduce(function(res, value) {
if (!res[value.category]) {
res[value.category] = {
category: value.category,
count: 0,
dishes: dishesArray.push(value.name), // problem here
};
groupByCategory.push(res[value.category]);
}
res[value.category].count += value.count;
return res;
}, {});
console.log(groupByCategory)
Expected output
[{category: "starters", count: 2, dishes:["Soup","Pâté"]},
{category: "desserts", count: 1, dishes:["Sticky toffee"]}]
As mentioned, a push returns an int
I believe you are looking for this much shortened reduce
const cartItems = [
{ id: 1, name: "Soup", price: 3, category: "starters", count: 1 },
{ id: 2, name: "Pâté", price: 5, category: "starters", count: 1 },
{ id: 9, name: "Sticky toffee", price: 18, category: "desserts", count: 1}
];
const groupByCategory = cartItems.reduce(function(res, value) {
const cat = value.category;
res[cat] = res[cat] || { category: cat, count: 0, dishes: [] };
res[cat].count += value.count;
res[cat].dishes.push(value.name)
return res;
}, {});
console.log(groupByCategory)

How to duplicate an object in an array by given quantity, ES6 and above

I'm trying to convert an array of objects where i return duplicated objects if the object properties quantity is greater than 1.
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
// desired return
[
{ id: 1, name: "Scissor", price: 2 }
{ id: 1, name: "Scissor", price: 2 }
{ id: 1, name: "Scissor", price: 2 }
{ id: 2, name: "Hat", price: 6.5}
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
{ id: 3, name: "Socks", price: 0.5 }
]
My code:
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
let newObjects= [];
Object.entries(objects).forEach(([key, value]) => {
for (let i=0; i < value.quantity; i++){
newObjects.push({ id: value.id, name: value.name, price: value.price})
}
});
console.log(newObjects);
So my code above does work, does return what i wanted, however i feel like there is a better/smoother and more of ES6 and beyond method. Could anyone please suggest a better way?
You could use .fill() and .flatMap().
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
let newObjects = objects.flatMap(e=>
Array(e.quantity).fill({id: e.id, name: e.name, price: e.price})
);
console.log(newObjects);
You can use an array reduce along with an array fill.
The map is required only if you want to have unique references otherwise you can fill using the same object.
const objects = [
{ id: 1, name: "Scissor", price: 2, quantity: 3 },
{ id: 2, name: "Hat", price: 6.5, quantity: 1 },
{ id: 3, name: "Socks", price: 0.5, quantity: 5 },
];
const output = objects.reduce((a, c) => {
return a.concat(Array(c.quantity).fill({}).map(x=>({
id: c.id,
name: c.name,
price: c.price
})))
}, []);
console.log(output)

Categories

Resources