Reputation: 1495
I have this type of object
var array = [
{ "foo": 1, "bar": 2, "baz": 3 },
{ "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 1, "bar": 2, "baz": 4 },
{ "foo": 2, "bar": 1, "baz": 3 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 }
]
and If 'foo' and 'bar' key values are same then choose key 'baz' greater value and remove other objects.
like this
[ { "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 } ]
I tried this solution but it's not working for me. This question is not like my question.
So, what is the solution in underscore/lodash library or in javascript only.
Upvotes: 0
Views: 115
Reputation: 12990
Another possibility is to sort the array by ascending order of foo
and bar
and descending order of baz
and then do a reduce
.
var array = [
{ "foo": 1, "bar": 2, "baz": 3 },
{ "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 1, "bar": 2, "baz": 4 },
{ "foo": 2, "bar": 1, "baz": 3 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 }
];
const res = array
.sort((a, b) => a.foo - b.foo || a.bar - b.bar || b.baz - a.baz)
.reduce((acc, curr) => {
const prev = acc[acc.length - 1] || {};
if (!(curr.foo === prev.foo && curr.bar === prev.bar)) acc.push(curr);
return acc;
}, []);
console.log(res);
Upvotes: 1
Reputation: 8141
const array = [
{ foo: 1, bar: 2, baz: 3 },
{ foo: 1, bar: 2, baz: 5 },
{ foo: 1, bar: 2, baz: 4 },
{ foo: 2, bar: 1, baz: 3 },
{ foo: 2, bar: 1, baz: 7 },
{ foo: 1, bar: 3, baz: 4 }
];
const result = array.reduce((result, obj) => {
const resultObj = result.find(resultObj => obj.foo === resultObj.foo && obj.bar === resultObj.bar);
if (!resultObj) {
return [ ...result, obj ];
}
if (resultObj.baz > obj.baz) {
return result;
}
return [ ...result.filter(obj => obj !== resultObj), obj ];
}, []);
console.log(result);
Upvotes: 0
Reputation: 18515
You could also do first orderBy ... then keyBy and lastly values to get what you need:
var array = [ { "foo": 1, "bar": 2, "baz": 3 }, { "foo": 1, "bar": 2, "baz": 5 }, { "foo": 1, "bar": 2, "baz": 4 }, { "foo": 2, "bar": 1, "baz": 3 }, { "foo": 2, "bar": 1, "baz": 7 }, { "foo": 1, "bar": 3, "baz": 4 } ]
const result = _.values(_.keyBy(
_.orderBy(array, ['foo', 'bar', 'baz']), x=>`${x.foo}-${x.bar}`))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Or you can chain it as well via:
const result = _(array)
.orderBy(['foo', 'bar', 'baz'])
.keyBy(x => `${x.foo}-${x.bar}`)
.values()
.value()
Upvotes: 0
Reputation: 191976
With lodash you can group by the combination of the value of foo
and baz
. Then map the result, and select the object with the highest baz
value in each group:
var array = [
{ "foo": 1, "bar": 2, "baz": 3 },
{ "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 1, "bar": 2, "baz": 4 },
{ "foo": 2, "bar": 1, "baz": 3 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 }
]
var result = _.map(
_.groupBy(array, o => `${o.foo}-${o.bar}`),
g => _.maxBy(g, 'baz')
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
With vanilla JS you can reduce the array into an object (the accumulator), using a similar convention for the accumulator key (combination of bar
and baz
). Whenever an object from the array, and an object stored in the accumulator have the same key, the one with the highest baz
value is kept.
const array = [
{ "foo": 1, "bar": 2, "baz": 3 },
{ "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 1, "bar": 2, "baz": 4 },
{ "foo": 2, "bar": 1, "baz": 3 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 }
]
const result = Object.values(array.reduce((r, o) => {
const key = `${o.foo}-${o.bar}`
if(!r[key] || r[key].baz < o.baz) r[key] = o
return r
}, {}))
console.log(result)
Upvotes: 1
Reputation: 1495
I tried this solution and it's working for me,
this is the solution
var result = ab.reduce((p,c) => {var o = p.find(e => e.foo === c.foo && e.bar === c.bar);
!!o ? o.baz = (o.baz > c.baz ? o.baz : c.baz) : p.push(c);
return p;},[]);
but I didn't understand the flow of this code. So, I decided to extend the code and tried to understand the code
So, First I read about reduce and find and extended the code
var result = ab.reduce((newArray, singleObj) => {
var sameKeyValueObj = newArray.find(obj => {
return obj.foo === singleObj.foo && obj.bar === singleObj.bar
});
sameKeyValueObj ? sameKeyValueObj.baz = (
sameKeyValueObj.baz > singleObj.baz ? sameKeyValueObj.baz : singleObj.baz
) : newArray.push(singleObj);
return newArray;
}, []);
This is an understandable solution for me now. If someone has another good solution then please tell me.
Upvotes: 0