JavaScript如何使用forEach()在filter()内过滤数组

5

我有一个对象数组,我想根据对象的属性值对其进行过滤。我想通过不同的属性进行过滤,因此它需要是动态的。为此,我有一个输入字段,我在其中键入,然后过滤数组。因此,假设我有这两个不同的数组:

const array_one = [
  {id: 1, code: 'ABC123', name: 'John'},
  {id: 2, code: 'DEF456', name: 'Stew'},
    // ...
];

const array_two = [
  {id: 1, value: '012345', company: 'Company 01' },
  {id: 2, value: '678910', company: 'Company 02' },
    // ...
];

我希望有一个函数,可以基于name过滤第一个数组,同时如果我想要过滤第二个数组,我希望可以通过value进行过滤。
为此,我编写了以下函数:
filterArray(array: Array<any>, fields: Array<any>, value: string) {
    value = this.convertString(value);

    array = array.filter((item) => {
        fields.forEach(obj => {
            if ( item[obj] ) {
                const _newObj = this.convertString(item[obj]);
                if ( _newObj.indexOf(value) !== -1 ) {
                    console.log(item);
                    return item;
                }
            }
        });
    });

    return array;
}
// convertString() is just another function to replace accents, spaces, etc...

然后我这样调用它:
filterArray(originalArray, ['name'], valueFromInput);

// or...
filterArray(originalArray, ['value'], valueFromInput);

// or even...
filterArray(originalArray, ['value', 'company'], valueFromInput);

但是被过滤的数组总是返回空,即使在indexOf验证中控制台打印了正确的对象。

我在这里做错了什么?因为它可以正确地进行过滤,我已经手动检查过了,但它不会添加到新的过滤数组中。


1
请更清楚地说明您期望的结果。使用 forEach() 时,在回调中返回某些内容将不会产生任何效果。如果您想将每个项目映射到其他内容,请使用 map()。如果您正在定义函数体,就像您为 filter() 回调所做的那样,必须使用 return 关键字,否则该回调将隐式返回 undefined - Lennholm
1
在JavaScript中,forEach没有返回值,所以当你返回item时,它只是被忽略了。但是filter需要一个可以强制转换为真或假值的返回值。你在filter内部没有返回任何东西,这就是为什么你没有得到一个过滤后的数组的原因。 - shadymoses
2个回答

12

您可以使用 Array#some 迭代 fields,如果其中一个等于 value,则返回 item

const array_one = [
  {id: 1, code: 'ABC123', name: 'John'},
  {id: 2, code: 'DEF456', name: 'Stew'}
];

const array_two = [
  {id: 1, value: '012345', company: 'Company 01' },
  {id: 2, value: '678910', company: 'Company 02' }
];

const filterArray = (array, fields, value) => {
  fields = Array.isArray(fields) ? fields : [fields];
  
  return array.filter((item) => fields.some((field) => item[field] === value));
};
  
console.log(filterArray(array_one, 'name', 'Stew'));

console.log(filterArray(array_two, ['id', 'company'], 2));

console.log(filterArray(array_two, ['id', 'company'], 'Company 02'));


1
唯一的区别在于我需要检查字段是否包含值,而不是比较整个值,所以我只需更改为: item[field].indexOf(value) !== -1。感谢您的帮助! - celsomtrindade

2

如果您想让过滤器涉及多个字段,则发送到函数的值也应该是数组。在下面的代码中,我假设您希望返回实现所有条件(包含您使用相同值向函数发送的所有属性的对象)的对象。

 const array_one = [
      {id: 1, code: 'ABC123', name: 'John'},
      {id: 2, code: 'DEF456', name: 'Stew'},
   ];

   const array_two = [
      {id: 1, value: '012345', company: 'Company 01' },
      {id: 2, value: '678910', company: 'Company 02' },
   ];

   function filterArray(array, fields, value) {
       array = array.filter((item) => {
           const found = fields.every((field, index) => { 
               return item[field] && item[field] === value[index]
           })
           return found
       });
       return array;
   }

   console.log(filterArray(array_one, ['name'], ['Stew']));

   console.log(filterArray(array_two, ['id', 'company'], [1,'Company 01']));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接