如果几个键值对相同​​且另一个键值小于其他对象,则从对象数组中删除对象

时间:2018-10-19 21:28:45

标签: javascript underscore.js lodash

我有这种类型的对象

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 } 
]

如果“ foo”和“ bar”键值相同,则选择更大的键“ baz”并删除其他对象。

像这样

[ { "foo": 1, "bar": 2, "baz": 5 },
{ "foo": 2, "bar": 1, "baz": 7 },
{ "foo": 1, "bar": 3, "baz": 4 } ]

我尝试了这个solution,但对我来说不起作用。 这个question与我的问题不同。

那么,下划线/ lodash库或仅在javascript中的解决方案是什么。

5 个答案:

答案 0 :(得分:1)

使用lodash可以按foobaz的值组合。然后映射结果,并在每个组中选择具有最高baz值的对象:

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>

使用香草JS,可以使用类似的累加键(barbaz组合)将数组简化为对象(累加器)。每当数组中的对象和存储在累加器中的对象具有相同的键时,baz值最高的键就会被保留。

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)

答案 1 :(得分:1)

另一种可能性是按照foobar的升序和baz的降序对数组进行排序,然后执行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);

答案 2 :(得分:0)

我尝试了这个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;},[]);

但是我不明白这段代码的流程。因此,我决定扩展代码并尝试理解代码

因此,首先我了解了reducefind并扩展了代码

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;
}, []);

这对我来说是一个可以理解的解决方案。如果有人还有其他好的解决方案,请告诉我。

答案 3 :(得分:0)

您也可以先进行orderBy ...然后进行keyBy,最后进行values来获得所需的内容:

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>

或者您也可以通过以下方式chain

const result = _(array)
  .orderBy(['foo', 'bar', 'baz'])
  .keyBy(x => `${x.foo}-${x.bar}`)
  .values()
  .value()

答案 4 :(得分:0)

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