JavaScript从数组中过滤值

3

我有一个包含数组的数组,每个子数组都包含两个元素。如何通过筛选第一个元素来返回数组中的第二个元素?

例如,我有以下数组,我的函数应该返回每个子数组的第二个元素,其中第一个项为8

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];

期望的结果是:['first', 'second', 'third']

目前我已经实现了以下内容,但是它返回的是每个数组中匹配到的两个元素而不仅仅是第二个元素...

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = array.filter(function(item){
  if(item[0] == 8) {
    return item[1];
  }
});
console.log(result);


“filter”不是“map” - 我认为你想要的是“map”(并使用“filter”来过滤掉不需要的结果) - Jaromanda X
我同意上面的评论:我认为你需要重新阅读有关filter的文档。根据您的过滤函数的返回值,它将保留或不保留当前元素。它不会修改它或使用您返回的对象。 - sjahan
7个回答

5
你可以使用条件进行过滤,然后只映射你想要的部分。在单个循环中,只有使用Array#reduce才可能实现,因为这里可以操作结果集的值。Array#filter返回数组的原始项,而不改变任何内容。对于过滤,回调需要返回一个被解释为布尔值的值,也就是说,每个真值(如对象、数组或任何非零数字等)都将取出该项放入结果集。如果您只想使用内部数组的一部分,并且该部分是真值,则过滤起作用,但它不会取回返回值,因为它不是为此而设计的。

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']],
    result = array.filter(function(item){
        return item[0] === 8;
    }).
    map(function (a) {
        return a[1];
    });

console.log(result);


你能解释一下为什么这不起作用吗?var ans = array.filter((a) => {if(a[0] == 8) return a[1]}) - lone_worrior
Array#filter过滤数组,删除未通过“过滤测试”的元素,但不以其他方式更改数组。Array#map更改数组,但不删除元素。 - notrota
1
@Valip,你可以稍后使用result = result.slice(0, 2)来截取数组的前两个元素。 - Nina Scholz

2

Array.prototype.filter 返回通过提供的谓词的元素,因此在您的情况下,这将是对于其为真的item。要实现您想要的效果,您需要首先过滤项目,然后使用map提取第二个元素:

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = array.filter(function(item) {
  return item[0] == 8;
}).map(function (item) {
  return item[1];
});
console.log(result);

或者使用 reduce:

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = array.reduce(function(result, item) {
  return item[0] == 8 ? result.concat(item[1]) : result;
}, []);
console.log(result);

如果你想使用ES6的功能,它可以变得更短:

const array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
const result1 = array.filter(([item]) => (item == 8)).map(([,item]) => item);
const result2 = array.reduce((res, [n, str]) => n == 8 ? [...res, str] : res, []);

console.log(result1);
console.log(result2);

编辑:要理解为什么您的函数无法正常工作,您需要了解 Array.prototype.filter() 的工作原理。它创建一个新数组,由提供的谓词函数(即检查某些条件并返回布尔值)返回 true 的元素组成。对于所有子数组,第一个元素为 8,第二个元素将决定是否使用该元素来创建新数组。

因此,对于 array 的每个元素(首先是[8,'first'],然后是[8,'second']等),将评估您的函数,并将为其返回 true 的元素添加到新数组中:

[[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']]
true,          true,          false,        true,         false

=> [[8, 'first'], [1, 'empty'], [8, 'third']]

你能解释一下为什么这不起作用吗? var ans = array.filter((a) => {if(a[0] == 8) return a[1]}) - lone_worrior
我已经更新了我的回答。如果有更多问题,请告诉我。 - Andrzej Smyk

1
你可以使用函数reduce

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];

var result = array.reduce(function(acc, item){
  if(item[0] === 8){
    acc.push(item[1])
   }
   return acc;
}, []);

console.log(result);

Array#reduce它将在单个循环中完成。


0
首先进行映射,然后使用过滤器来删除未定义的值。

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = array.map(function(item){
  if(item[0] == 8) {
    return item[1];
  }
}).filter(function(item) {
    return item;
});
console.log(result);


0

你需要同时筛选出你不想要的条目 并且 将这些条目映射到条目中的第二个值。

一般来说,最好的方式是先进行筛选,然后再进行映射

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = array.filter(function(item){ return item[0] == 8; })
                  .map(function(item) { return item[1]; });
console.log(result);

...但对于一个非常大的数据集,如果您不想进行多次遍历,可以使用filterMap函数:

function filterMap(arr, predicate) {
    var result = [];
    arr.forEach(function(entry) {
      var newEntry = predicate(entry);
      if (newEntry !== undefined) {
          result.push(newEntry);
      }
    });
    return result;
}
var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = filterMap(array, function(item){
    return item[0] == 8 ? item[1] : undefined;
});
console.log(result);

该版本假设您从结果中永远不想要一个undefined条目,但您可以根据需要进行调整。例如,如果您希望它成为真正的通用型,您可以在filterMap上放置一个唯一值,表示“将其排除在外”:

function filterMap(arr, predicate) {
    var result = [];
    arr.forEach(function(entry) {
      var newEntry = predicate(entry);
      if (newEntry !== filterMap.OMIT) {
          result.push(newEntry);
      }
    });
    return result;
}
filterMap.OMIT = {};
var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];
var result = filterMap(array, function(item){
    return item[0] == 8 ? item[1] : filterMap.OMIT;
});
console.log(result);

虽然你可以使用reduce来实现这个功能,但是在“累加器”不变的情况下,reduce并不是最好的选择。因此,如果你经常需要这样做,请给自己创建一个实用程序来完成它。或者只需使用filtermap


0

数组的 filter 方法通过在每次迭代中传递满足特定条件的项目来创建一个新数组。

试试这个:

var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 
'empty']],resArray = [];
array.forEach(function(item){
  if(parseInt(item[0]) === 8){
    resArray.push(item[1]);
  }
});
console.log(resArray);

-2
你可以使用 Array.reduce 来实现你想要的输出 -
var array = [[8, 'first'], [8, 'second'], [1, 'empty'], [8, 'third'], [9, 'empty']];


array.reduce(function(i, n){
    if(n[0]==8){
        i.push(n[1]);
    }
    return i;
},[]);
//output : ['first', 'second', 'third']

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