ES6 Фильтрация объектов по уникальному атрибуту - PullRequest
1 голос
/ 12 апреля 2020

У меня есть массив ошибок, каждая ошибка имеет неуникальный атрибут param.

Я бы хотел отфильтровать массив на основе того, видел ли param ранее.

Примерно так:

const filteredErrors = [];
let params = [];

for(let x = 0; x < errors.length; x++) {
    if(!params.includes(errors[x].param)) {
        params.push(errors[x].param);
        filteredErrors.push(errors[x]);
    }
}

Но я не знаю, как это сделать в ES6.

Я могу получить уникальные параметры const filteredParams = Array.from(new Set(errors.map(error => error.param))); , но не объекты сами по себе.

Я уверен, что это просто слабость в моем понимании функций высшего порядка, но я просто не могу gr asp it

Ответы [ 5 ]

2 голосов
/ 12 апреля 2020

Вместо массива вы можете использовать объект, чтобы сохранить карту существующих значений и использовать функцию фильтра

let params = {};

const filteredErrors = errors.filter(error => {
   if(params[error.param]) return false;
   params[error.param] = true;
   return true;
});
2 голосов
/ 12 апреля 2020

Вы можете уничтожить param, проверить по params, добавить значение в params и вернуть true для получения объекта в качестве результата фильтрации.

В результате вы получите массив первых найденных ошибок того же типа.

const
    params = [],
    filteredErrors = errors.filter(({ param }) =>
        !params.includes(param) && params.push(param));
1 голос
/ 12 апреля 2020

Если у вашего параметра есть идентификатор флага, если этот параметр был виден раньше, тогда вы можете просто сделать это.

const filteredErrors = errors.filter(({ param }) => param.seen === true);

ИЛИ

const filteredErrors = errors.filter((error) => error.param.seen);

ошибки должны быть массивом объектов .

где param - одно из полей элемента массива, а видимое - одно из полей объекта param.

1 голос
/ 12 апреля 2020

Вы можете сделать это, используя Array.prototype.reduce. Вам нужно перебрать объекты в массиве и сохранить найденное params в Set, если его там еще нет.

Set.prototype.has позволит вам это выяснить. Если он отсутствует в Set, вы добавляете его как в экземпляр Set, так и в конечный накопленный массив, так что на следующей итерации, если param присутствует в вашем Set, вы не включаете его объект:

const errors = [{param: 1, val: "err1"}, {param: 2, val: "err2"},  {param: 3, val: "err3"},  {param: 2, val: "err4"}, {param: 1, val: "err5"}];

const { filteredParams } = errors.reduce((acc, e) => {
  !acc.foundParams.has(e.param) && (acc.foundParams.add(e.param) && 
                                    acc.filteredParams.push(e));
  return acc;
}, {foundParams: new Set(), filteredParams: []});
console.log(filteredParams);
1 голос
/ 12 апреля 2020

я, вероятно, сделал бы это так с reduce и не нуждался бы во внешних параметрах:

const filteredErrors = Object.values(
  errors.reduce((acc, val) => {
    if (!acc[val.param]) {
      acc[val.param] = val;
    }
    return acc;
  }, {}))

в основном преобразует его в объект, введенный параметром с объектом в качестве значений, только устанавливая ключ, если он не был установлен ранее, затем вернитесь в массив значений.

обобщенно, как и так

function uniqueBy(array, prop) {
  return Object.values(
    array.reduce((acc, val) => {
      if (!acc[val[prop]]) {
        acc[val[prop]] = val;
      }
      return acc;
    }, {}))
}

, тогда просто сделайте:

const filteredErrors = uniqueBy(errors, 'param');
...