简体   繁体   English

Javascript过滤数组中的值

[英]Javascript filter values from array

I have an array of arrays and each of those arrays contain two elements. 我有一个数组数组,每个数组包含两个元素。 How can I return the second element from array by filtering the first element? 如何通过过滤第一个元素从数组中返回第二个元素?

For example I have the following array and my function should return the second element from each sub-array where the first item is 8 : 例如,我有以下数组,我的函数应该返回第一项为8每个子数组中的第二个元素:

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

Expected result: ['first', 'second', 'third'] 预期结果: ['first', 'second', 'third']

This is what I've implemented so far, but it returns both elements instead of just the second one from each array with a match... 这是我到目前为止实现的,但它返回两个元素而不是每个数组中的第二个元素匹配...

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

You could filter with the condition and then you need to map only the part, you want. 您可以使用条件进行过滤,然后您只需要映射您想要的部分。

In a single loop it is only possible with Array#reduce , because here you can manipulate the value for the result set. 在单个循环中,只能使用Array#reduce ,因为在这里您可以操作结果集的值。

Array#filter returns the original item of the array, without changing something. Array#filter返回Array#filter的原始项,而不更改任何内容。

The filter() method creates a new array with all elements that pass the test implemented by the provided function. filter()方法创建一个新数组,其中包含所有传递由提供的函数实现的测试的元素。

For filtering, the callback needs to return a value which is interpreted as boolean, that means, every truthy value (like an object, array, or any not zero number, etc) takes the item for the result set. 对于过滤,回调需要返回一个被解释为boolean的值,这意味着每个truthy值(如对象,数组或任何非零数字等)都会获取结果集的项。

If you like to use only a part of the inner array and the part is a truty value, then filtering works, but it does not take the return value, because it is not made for that. 如果你只想使用内部数组的一部分并且该部分是一个truty值,那么过滤可以工作,但它不会获取返回值,因为它不是为此而设的。

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

Array.prototype.filter returns element that passes provided predicate, so in you case that will be item for which item 1 is true. Array.prototype.filter返回及格,谓语,所以在你的情况下,这将是件item的哪个项目1是正确的。 To achieve what you want, you need to filter items first and the extract secon element using map : 要实现您想要的效果,您需要先使用map过滤项目和提取secon元素:

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

Or use reduce: 或者使用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); 

If you want to use features of ES6 it can get event shorter: 如果您想使用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); 

EDIT: To understand why your function is not working you need to understand how Array.prototype.filter() works. 编辑:要了解您的函数无法正常工作的原因,您需要了解Array.prototype.filter()工作原理。 It creates a new array made of elements for which provided predicate function (ie checking some condition and returning Boolean) returns true. 它创建一个由元素组成的新数组,为其提供谓词函数(即检查某些条件并返回布尔值)返回true。 For all subarrays that have 8 as first item, second element will decide if that element will be used for creating new array. 对于具有8作为第一项的所有子数组,第二个元素将决定该元素是否将用于创建新数组。

So for each element of array (first [8, 'first'] , next [8, 'second'] etc.) your function will be evaluated, and element for which true is returned, will be added to new array: 因此,对于array每个元素(first [8, 'first'] ,next [8, 'second']等),将评估您的函数,并将返回true的元素添加到新数组中:

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

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

You could use function reduce 你可以使用函数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 It will finish in a single loop. Array#reduce它将在一个循环中完成。

Array's filter method creates a new array by passing the item that pass certain condition in each iteration. Array的filter方法通过传递在每次迭代中传递特定条件的项来创建新数组。

Try out this: 试试这个:

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

First map, then filter to remove undefined values. 第一个映射,然后过滤以删除未定义的值。

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

You need to both filter out the entries you don't want and map the entries to just the second value in the entry. 必须同时过滤掉你不想要的条目条目映射到刚刚在条目中的第二个值。

In general, the best way is to filter then map : 一般来说,最好的方法是filter然后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); 

...but for a really large data set, if you don't want to make multiple passes, you can give yourself a filterMap function: ...但是对于一个非常大的数据集,如果你不想进行多次传递,你可以给自己一个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); 

That version assumes you never want an undefined entry in the result, but you can tweak as desired. 该版本假设您从不希望结果中存在undefined条目,但您可以根据需要进行调整。 For instance, if you want it to be really general purpose, you'd put a unique value on filterMap which indicated "leave this out": 例如,如果您希望它真的是通用的,那么您将在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); 

While you can shoehorn reduce to do this, reduce isn't really great for situations where the "accumulator" doesn't change. 虽然你可以通过鞋拔reduce来做到这一点,但对于“累加器”不会改变的情况, reduce并不是很好。 So if you do this frequently, give yourself a utility to do it. 因此,如果您经常这样做,请给自己一个实用工具。 Or just filter and map . 或者只是filtermap

You can utilize Array.reduce to achieve your desired output - 您可以利用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']

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

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