Related
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)
My nested json array looks like:
[
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
]
Now I get a id like "11"
then get the parent ids array in json like [6,9,11]
How to do?
var id = 11
console.log(findParent(id))
//result is [6,9,11]
You need to do recursive search
const persons = [
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
];
function searchRecursive(items, id) {
const allIds = [];
items.forEach(item => {
if(item.id === id) {
allIds.push(item.id);
}
else if(item.children) {
const ids = searchRecursive(item.children, id);
if(ids.length) allIds.push(item.id);
ids.forEach(id => allIds.push(id));
}
});
return allIds;
}
console.log(searchRecursive(persons, 11));
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);
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)
I've array like this :
people = [
{id:1,name:'abc',age:18},
{id:2,name:'abcd',age:20},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:7,name:'abci',age:17},
]
Now I want Sorting an array order by frequency of occurence(age) in JavaScript.
Output like this:
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]
So how I can do it ?
I've tried follow answer of Nina Scholz but i've a bug like this.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
Output is :
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]
Just count ages and sort descending by the count.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For sorting by count and age, add a logical OR || along with the delta of the ages.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) =>
count[b.age] - count[a.age] ||
b.age - a.age
);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this:
let people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }];
let tmpAge = {};
for (let i = 0; i < people.length; i++) {
if (!tmpAge[people[i].age]) {
tmpAge[people[i].age] = 1;
} else {
tmpAge[people[i].age]++;
}
}
people.sort((a, b) => tmpAge[b.age] - tmpAge[a.age]);
console.log(people);
const people = [
{ id: 1, name: 'abc', age: 18 },
{ id: 2, name: 'abcd', age: 20 },
{ id: 3, name: 'abce', age: 18 },
{ id: 4, name: 'abcf', age: 18 },
{ id: 5, name: 'abcg', age: 21 },
{ id: 6, name: 'abch', age: 20 },
{ id: 7, name: 'abci', age: 17 },
];
const agesFrequency = people.reduce((previousValue, currentValue) => {
const { age } = currentValue;
return {
...previousValue,
[age]: (
previousValue[age] || 0
) + 1,
};
}, {});
people.sort((
(a, b) =>
agesFrequency[b.age] - agesFrequency[a.age]
));
console.log(people);
I solved it . Change function sort to
people.sort((a, b) => {
if (count[b.age] === count[a.age]) {
if (b.age < a.age) {
return -1;
}
if (b.age > a.age) {
return 1;
}
return 0;
} else if (count[b.age] < count[a.age]) {
return -1;
}
});
Posted on behalf of OP