Merge Duplicate object in array - javascript

I have an array I need to merge duplicate values with the sum of amount.
What would be an efficient algorithm
var arr = [{
item: {
id: 1,
name: "Abc"
},
amount: 1
}, {
item: {
id: 1,
name: "Abc"
},
amount: 2
}, {
item: {
id: 2,
name: "Abc"
},
amount: 2
},{
item: {
id: 1,
name: "Abc"
},
amount: 2
}]
I need solution as
[{
item: {
id: 1,
name: "Abc"
},
amount: 5
}, {
item: {
id: 2,
name: "Abc"
},
] amount: 2
}]

simply use Object.values() with Array.reudce() to merge objects and then get the values:
var arr = [{ item: { id: 1, name: "Abc" }, amount: 1 }, { item: { id: 1, name: "Abc" }, amount: 2 }, { item: { id: 2, name: "Abc" }, amount: 2 },{ item: { id: 1, name: "Abc" }, amount: 2 }];
var result = Object.values(arr.reduce((a,curr)=>{
if(!a[curr.item.id])
a[curr.item.id] = Object.assign({},curr); // Object.assign() is used so that the original element(object) is not mutated.
else
a[curr.item.id].amount += curr.amount;
return a;
},{}));
console.log(result);

used map to catch em all :D
var arr = [{ item: { id: 1, name: "Abc" }, amount: 1 }, { item: { id: 1, name: "Abc" }, amount: 2 }, { item: { id: 2, name: "Abc" }, amount: 2 },{ item: { id: 1, name: "Abc" }, amount: 2 }];
var res = {};
arr.map((e) => {
if(!res[e.item.id]) res[e.item.id] = Object.assign({},e); // clone, credits to: #amrender singh
else res[e.item.id].amount += e.amount;
});
console.log(Object.values(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 reduce an array and add a count as a new field?

I have an array of objects, however i need the array to add a count onto each object, and also remove any duplicates. Is there a simple way to achieve this?
CURRENT
[
{ id: 2, name: 'Adventure' },
{ id: 6, name: 'Crime' },
{ id: 2, name: 'Adventure' },
{ id: 3, name: 'Beautiful' },
{ id: 7, name: 'Drama' },
{ id: 2, name: 'Adventure' }
]
EXPECTED
[
{ id: 2, name: 'Adventure', count: 3 },
{ id: 6, name: 'Crime', count: 1 },
{ id: 3, name: 'Beautiful', count: 1 },
{ id: 7, name: 'Drama', count: 1 }
]
let current = [
{ id: 2, name: 'Adventure' },
{ id: 6, name: 'Crime' },
{ id: 2, name: 'Adventure' },
{ id: 3, name: 'Beautiful' },
{ id: 7, name: 'Drama' },
{ id: 2, name: 'Adventure' }
]
let expected = current.reduce((acc, cur) => {
let curFind = acc.find(item => item.id === cur.id)
if (curFind) {
curFind.count++
return acc
} else {
return [...acc, {
...cur,
count: 1
}]
}
}, [])
console.log('expected:', expected)

How to enumare objects and total of them with the same key with another object in array js

I'm populing a pdf template with an array of employees, and now I need to count the number of employees working in a same department, I found a way to count the total of concurrences but I can't enumarate the employee working in the department and the total of them. Can you help me? Thanks!!!
For example, I have this array of objects
const employees = [
{
id: 1,
name: "john",
department: {
id: 1,
},
},
{
id: 1,
name: "Mike",
department: {
id: 3,
},
},
{
id: 1,
name: "Leona",
department: {
id: 1,
},
},
{
id: 1,
name: "Lara",
department: {
id: 1,
},
},
];
Result Expected:
const employees = [
{
id: 1,
name: "john",
department: {
id: 1,
},
totalForDeparments: "1/3",
},
{
id: 1,
name: "Mike",
department: {
id: 3,
},
totalForDeparments: "1/1",
},
{
id: 1,
name: "Leona",
department: {
id: 1,
},
totalForDeparments: "2/3",
},
{
id: 1,
name: "Lara",
department: {
id: 1,
},
totalForDeparments: "3/3",
},
];
First you group by the department.id - then you can iterate the original array adding the correct indexes.
const employees = [{id:1,name:"john",department:{id:1}},{id:1,name:"Mike",department:{id:3}},{id:1,name:"Leona",department:{id:1}},{id:1,name:"Lara",department:{id:1}},];
var grouped = employees.reduce(function(agg, item) {
agg[item.department.id] = agg[item.department.id] || {
count: 0,
current: 0
}
agg[item.department.id].count++;
return agg;
}, {});
employees.map(function(item) {
var data = grouped[item.department.id]
data.current++;
item.totalForDeparments = data.current + "/" + data.count
})
console.log(employees)
.as-console-wrapper {max-height: 100% !important}

search an item in multidimentionnal array

I'm trying to find an element on a multidimentionnal array usin JAVASCRIPT function, but I get error
This is my array's data:
export const datas = [
{
id: 1,
firstName: 'John',
tables: [
{ ID: 11, title: 'Lorem' },
{ ID: 12, title: 'Ipsum' },
],
},
{
id: 2,
firstName: 'Doe',
tables: [
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
{ ID: 23, title: 'Korem' },
],
},
{
id: 3,
firstName: 'Brad',
tables: [
{
ID: 30,
title: 'Mern',
nodes: [{ name: 'Name4' }, { name: 'Name5' }, { name: 'Name6' }],
},
{
ID: 31,
title: 'Full',
nodes: [{ name: 'Name7' }, { name: 'Name8' }, { name: 'Name9' }],
},
],
},
];
I've tried a reccursive function but it's not work, this is my code :
export const findById = (arr, id) => {
for (let o of arr) {
if (o.tables.length > 0) {
let a = findById(o.tables.nodes, 'id');
console.log(a);
}
}
};
I want to print the Object with ID 22, the problem is that I don't have the same structure in each dimension, and it still confuse me..
My Input : 22
My output :
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
Have you an idea how to edit my function to get my input's response ?
Your recursive function wasn't too far off, you need to check if the item as a tables first before recursively calling it again. And then finally just check the ID in the loop.
eg..
const datas=[{id:1,firstName:"John",tables:[{ID:11,title:"Lorem"},{ID:12,title:"Ipsum"}]},{id:2,firstName:"Doe",tables:[{ID:22,title:"Arke",nodes:[{name:"Name1"},{name:"Name2"},{name:"Name3"}]},{ID:23,title:"Korem"}]},{id:3,firstName:"Brad",tables:[{ID:30,title:"Mern",nodes:[{name:"Name4"},{name:"Name5"},{name:"Name6"}]},{ID:31,title:"Full",nodes:[{name:"Name7"},{name:"Name8"},{name:"Name9"}]}]}];
function findById(arr, ID) {
for (const a of arr) {
if (a.tables) {
const r = findById(a.tables, ID);
if (r) return r;
}
if (a.ID === ID) return a;
}
}
console.log(findById(datas, 22));
if you just need the nested data you can use flatMap and find
const findById = (arr, id) =>
arr
.flatMap(d => d.tables)
.find(t => t.ID === id)
const datas = [{
id: 1,
firstName: 'John',
tables: [{
ID: 11,
title: 'Lorem'
},
{
ID: 12,
title: 'Ipsum'
},
],
},
{
id: 2,
firstName: 'Doe',
tables: [{
ID: 22,
title: 'Arke',
nodes: [{
name: 'Name1'
}, {
name: 'Name2'
}, {
name: 'Name3'
}],
},
{
ID: 23,
title: 'Korem'
},
],
},
{
id: 3,
firstName: 'Brad',
tables: [{
ID: 30,
title: 'Mern',
nodes: [{
name: 'Name4'
}, {
name: 'Name5'
}, {
name: 'Name6'
}],
},
{
ID: 31,
title: 'Full',
nodes: [{
name: 'Name7'
}, {
name: 'Name8'
}, {
name: 'Name9'
}],
},
],
},
];
console.log(findById(datas, 22))
js has amazing array options https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
the ones which will help you most are probably:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
here are some examples
// get the base with id 22
const baseWith22ID = datas.filter(f => f.tables.filter(s => s.id = 22))
// (i guess you want this one) get all elements with id 22
const onlyElementsWith22ID = datas.flatMap(f => f.tables.filter(s => s.id = 22))

get name of object in array when option.amount equals zero

I'm trying to get an array of names of objects that have options.amount all equals to zero. Thanks for your time. This is what i tryed:
let variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0
},
{
name: 'cheese',
price: 1,
amount: 0
}
]
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1
},
{
name: 'mayo',
price: 1,
amount: 0
}
]
}
];
//Expected output = ['extra']
let arrayOfOptionsNames = variants.map(x => x.options.filter(y => y.amount === 0 ? x.name : 0))
console.log(arrayOfOptionsNames)
You could use Array.prototype.filter() and Array.prototype.every() method to get your result. Every method test if every elements of the array pass the test by the given callback function and returns a boolean value.
const variants = [
{
name: 'extra',
options: [
{
name: 'meat',
price: 3,
amount: 0,
},
{
name: 'cheese',
price: 1,
amount: 0,
},
],
},
{
name: 'sauce',
options: [
{
name: 'ketchup',
price: 2,
amount: 1,
},
{
name: 'mayo',
price: 1,
amount: 0,
},
],
},
];
const ret = variants
.filter((x) => x.options.every((y) => y.amount === 0))
.map((x) => x.name);
console.log(ret);
You could filter and get the wanted property.
let variants = [{ name: 'extra', options: [{ name: 'meat', price: 3, amount: 0 }, { name: 'cheese', price: 1, amount: 0 }] }, { name: 'sauce', options: [{ name: 'ketchup', price: 2, amount: 1 }, { name: 'mayo', price: 1, amount: 0 }] }],
result = variants
.filter(({ options }) => options.every(({ amount }) => !amount))
.map(({ name }) => name);
console.log(result);

Categories

Resources