简体   繁体   English

ES6 按唯一属性过滤对象

[英]ES6 Filtering objects by unique attribute

I've an array of errors, each error has a non-unique param attribute.我有一系列错误,每个错误都有一个非唯一的param属性。

I'd like to filter the array based on whether the param has been seen before.我想根据之前是否见过param来过滤数组。

Something like this:像这样的东西:

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

But I've no idea how to do this in ES6.但我不知道如何在 ES6 中做到这一点。

I can get the unique params const filteredParams = Array.from(new Set(errors.map(error => error.param)));我可以得到唯一的参数const filteredParams = Array.from(new Set(errors.map(error => error.param))); but not the objects themselves.但不是对象本身。

Pretty sure this is just a weakness in my understanding of higher order functions, but I just can't grasp it很确定这只是我对高阶函数理解的一个弱点,但我就是无法理解

You could destrucure param , check against params and add the value to params and return true for getting the object as filtering result.您可以破坏param ,检查params并将值添加到 params 并返回true以获得 object 作为过滤结果。

As result you get an array of first found errors of the same type.结果,您将获得一组首次发现的相同类型的错误。

const
    params = [],
    filteredErrors = errors.filter(({ param }) =>
        !params.includes(param) && params.push(param));

i'd probably do it like this with a reduce and no need for outside parameters:我可能会这样做, reduce并且不需要外部参数:

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

basically convert it into an object keyed by the param with the object as values, only setting the key if it hasn't been set before, then back into an array of the values.基本上将其转换为由参数键入的 object 并以 object 作为值,仅在之前未设置的情况下设置键,然后返回值的数组。

generalized like so像这样概括

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

then just do:然后做:

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

You can do it by using Array.prototype.reduce .您可以使用Array.prototype.reduce来完成。 You need to iterate through the objects in the array and keep the found params in a Set if it is not already there.您需要遍历数组中的对象并将找到的params保留在Set中(如果它不存在的话)。

The Set.prototype.has will let you find that out. Set.prototype.has会让你发现这一点。 If it is not present in the Set you add it both in the Set instance and the final accumulated array, so that in the next iteration if the param is present in your Set you don't include that object:如果Set中不存在它,则将它添加到Set实例和最终累积的数组中,以便在下一次迭代中,如果param存在于Set中,则不包括 object:

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

Instead of an array you can make use of an object to keep a map of existing values and make use of filter function您可以使用 object 来保留现有值的 map 并使用过滤器 function 而不是数组

let params = {};

const filteredErrors = errors.filter(error => {
   if(params[error.param]) return false;
   params[error.param] = true;
   return true;
});

If your param has a flag identifier if this param has been seen before then you can simply do this.如果你的参数有一个标志标识符,如果这个参数之前已经见过,那么你可以简单地做到这一点。

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

OR或者

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

errors should be an array of objects.错误应该是一个对象数组。

where param is one of the fields of the element of array errors and seen is one of the fields of param object.其中 param 是数组错误元素的字段之一, seen 是参数 object 的字段之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM