Grouping array by same property value, iterate over that array - javascript

I have the following array:
var results = [
{ group: 1,
department: 2,
total: 10 },
{ group: 1,
department: 2,
total: 25 },
{ group: 1,
department: 3,
total: 15 },
{ group: 1,
department: 3,
total: 5 },
{ group: 2,
department: 4,
total: 10},
{ group: 2,
department: 4,
total: 50 }
]
I need to arrange the array into a 2D nested array, where the sub arrays are Group 1 and Group 2. The sub arrays should also be parent arrays, whose children are ordered by Department, like so:
var results:[
{
group1:[
{
department2:[
{
group:1,
department:2,
total:10
},
{
group:1,
department:2,
total:25
},
{
group:1,
department:3,
total:15
}
]
},
{
department3:[
{
group:1,
department:3,
total:5
}
]
}
]
},
{
group2:[
{
department4:[
{
group:2,
department:4,
total:10
},
{
group:2,
department:4,
total:50
}
]
}
]
}
]
This is for a react component, where I need to print each one as a row, but add a total after all the department groups are done, and then one after each group, and then a total after everything.
Perhaps I´m over complicating it and there is a better way?

var results = [
{ group: 1,
department: 2,
total: 10 },
{ group: 1,
department: 2,
total: 25 },
{ group: 1,
department: 3,
total: 15 },
{ group: 1,
department: 3,
total: 5 },
{ group: 2,
department: 4,
total: 10},
{ group: 2,
department: 4,
total: 50 }
]
var nested_result = {}
results.forEach(obj => {
if(nested_result[obj.group] === undefined) {
nested_result[obj.group] = {};
}
if(nested_result[obj.group][obj.department] === undefined) {
nested_result[obj.group][obj.department] = [];
}
nested_result[obj.group][obj.department].push(obj);
})
console.log(nested_result);

var results = [
{ group: 1, department: 2, total: 10 },
{ group: 1, department: 2, total: 25 },
{ group: 1, department: 3, total: 15 },
{ group: 1, department: 3, total: 5 },
{ group: 2, department: 4, total: 10},
{ group: 2, department: 4, total: 50 }
]
var outObj = {};
var out = results.map(function(a) {
var groupName = 'group' + a.group;
typeof outObj[groupName] == 'undefined' && ( outObj[groupName] = {});
var depName = 'department' + a.department;
typeof outObj[groupName][depName] == 'undefined' && ( outObj[groupName][depName] = [] );
outObj[groupName][depName].push(a );
});
console.log( outObj );

Related

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}

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)

Counting number of occurances of in primary array A that are in array B

I want to get the count of Items in array A that are in B and return an array C that contains the count elements.
array A is:
arrA = [{id:1,name:"Nairobi"},{id:2,name:"New Delhi"},{id:3,name:"Singapore"},{id:4,name:"London"}]
array B is:
arrB = [{id:1,id_fk:1,name:"Steve"},{id:2,id_fk:1,name:"John"},{id:3,id_fk:2,name:"Stella"},{id:4,id_fk:3,name:"Kemi"},{id:5,id_fk:3,name:"Kelly"},{id:6,id_fk:4,name:"James"},{id:7,id_fk:4,name:"Marley"},{id:8,id_fk:4,name:"Oliver"}]
Using id_fk in array B as a "foreign key" for id in array A, the expected output is
[2,1,2,3]
My implementation code is
for (let arrayA of arrA){
let count = arrB.filter(a =>
{return a.id_fk === arrayA.id}).length;
}
You could take a Map and get the id as keys in the wanted order and reduce the second array for counting items with id_fk. As result take an array of the values of the map.
This approach uses a single loop for getting the id as keys and another loop for counting.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
result = Array.from(arrB
.reduce(
(m, { id_fk }) => m.set(id_fk, m.get(id_fk) + 1),
new Map(arrA.map(({ id }) => [id, 0]))
)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A result with a hash table and new objects with a count property.
var arrA = [{ id: 1, name: "Nairobi" }, { id: 2, name: "New Delhi" }, { id: 3, name: "Singapore" }, { id: 4, name: "London" }],
arrB = [{ id: 1, id_fk: 1, name: "Steve" }, { id: 2, id_fk: 1, name: "John" }, { id: 3, id_fk: 2, name: "Stella" }, { id: 4, id_fk: 3, name: "Kemi" }, { id: 5, id_fk: 3, name: "Kelly" }, { id: 6, id_fk: 4, name: "James" }, { id: 7, id_fk: 4, name: "Marley" }, { id: 8, id_fk: 4, name: "Oliver" }],
hash = {},
result = arrA.map(o => Object.assign(hash[o.id] = {}, o, { count: 0 }));
arrB.forEach(({ id_fk }) => hash[id_fk].count++);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do it like this. https://jsfiddle.net/6egs7uLy/
let counts = [];
arrA.forEach((item, index) => {
let count = 0;
arrB.forEach((item2, index) => {
if(item['id'] === item2['id_fk']) {
count++;
}
})
counts.push(count);
count = 0;
})

Merge Duplicate object in array

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));

Categories

Resources