Удалить объект в массиве объектов, если несколько пар ключ-значение совпадают, а другое значение ключа меньше, чем у другого объекта - PullRequest
0 голосов
/ 20 октября 2018

У меня есть этот тип объекта

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

Я пробовал это решение , но оно у меня не работает.Этот вопрос не похож на мой вопрос.

Итак, что такое решение в библиотеке подчеркивания / lodash или только в javascript.

Ответы [ 5 ]

0 голосов
/ 20 октября 2018

Другая возможность - отсортировать массив по возрастанию foo и bar и по убыванию 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);
0 голосов
/ 20 октября 2018

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);
0 голосов
/ 20 октября 2018

С помощью lodash вы можете группировать по комбинации значений foo и baz.Затем сопоставьте результат и выберите объект с наибольшим значением 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>

С помощью vanilla JS вы можете преобразовать массив в объект (аккумулятор), используя аналогичное соглашение для ключа аккумулятора (комбинация bar и baz).Всякий раз, когда объект из массива и объект, сохраненный в аккумуляторе, имеют один и тот же ключ, ключ с наибольшим значением 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)
0 голосов
/ 20 октября 2018

Вы также можете сделать сначала orderBy ... затем keyBy и, наконец, значения чтобы получить то, что вам нужно:

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>

Или вы можете цепь , а также через:

const result = _(array)
  .orderBy(['foo', 'bar', 'baz'])
  .keyBy(x => `${x.foo}-${x.bar}`)
  .values()
  .value()
0 голосов
/ 20 октября 2018

Я попробовал это решение , и оно работает для меня,

это решение

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

, но я не понял, как работает этот код.Итак, я решил расширить код и попытался понять код

Итак, сначала я прочитал о уменьшение и найти и расширил код

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

Это понятное для меня решение сейчас.Если у кого-то есть другое хорошее решение, скажите, пожалуйста.

...