Reputation: 2675
I have an array like this.
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}]
I need to get an array like this:
var newData = [{
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}]
That is get the highest value for each 'name' key in an array.
This is what I have tried:
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}]
console.log(data.reduce(function(prev, current) {
return (prev.name !== current.name && prev.value > current.value) ? prev : current
}))
Please advice.
Upvotes: 0
Views: 887
Reputation: 1086
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}]
let result=data.reduce(function(temp, current) {
//check if temp has object
var found = temp.some((el) => {
return el.name === current.name
});
//if not found, add the object
if (!found) { temp.push(current) }
//if found and value is greater, replace the max value
else{
temp.find((element) => {
if(element.name === current.name && element.value<current.value)
element.value=current.value
})
}
return temp
},[])
console.log(result);
Upvotes: 0
Reputation: 13266
Use forEach
instead of reduce
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}]
let result = {};
data.forEach(function(current) {
if (result[current.name] &&
result[current.name].value < current.value &&
result[current.name].category === current.category) {
result[current.name].value = current.value;
} else if (!result[current.name]) {
result[current.name] = current;
}
});
console.log(Object.values(result));
Upvotes: 0
Reputation: 50291
Use reduce and check if the accumulator array has the same fruit using findIndex
. If it is -1 , then in accumulator array push the value else update the count in that index
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}]
let result = data.reduce(function(acc, curr) {
let findIfExist = acc.findIndex(elem => {
return elem.name === curr.name;
})
if (findIfExist === -1) {
acc.push(curr)
} else {
if (acc[findIfExist].value < curr.value) {
acc[findIfExist].value = curr.value
}
}
return acc;
}, [])
console.log(result)
Upvotes: 0
Reputation: 370679
You need to keep track of the current highest value
items for every name
, so you could try reducing into an object, whose keys are the name
s, and values are the currently winning value
s for that name. Then, get the resulting object's values:
var data = [{
name: 'Apple',
category: 'Fruit',
value: 12
}, {
name: 'Apple',
category: 'Fruit',
value: 20
}, {
name: 'Orange',
category: 'Fruit',
value: 65
}, {
name: 'Orange',
category: 'Fruit',
value: 40
}];
console.log(Object.values(
data.reduce((a, item) => {
const { name, value } = item;
if (!a[name] || a[name].value < value) a[name] = item;
return a;
}, {})
));
(Your prev.name !== current.name ...
method would only work if you're only trying to get one item out of it in the end - because you need more, you need an object that can contain multiple items.)
Upvotes: 4