获取满足条件的 JavaScript 数组元素的索引

14

我有一个像这样的数组:

[{prop1:"abc",prop2:"qwe"},{prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"}]

我想获取所有满足条件的元素的索引;在这种情况下,当prop1 == "abc"时。所需输出类似于[0,1]

苦于找不到一种简洁的方法来完成此操作?indexes = a.findIndex(x => x.prop1==="abc")将为上述数组返回0,因为它会停止在第一个成功找到的位置。

我觉得我需要像这样的东西:indexes = a.filter((x, index) => x.prop1==="abc").map(x => index)


“reduce”、“filter”和“map”,还是“for”循环最佳实践?哇,这么快就有很多答案了...这是一个愚蠢的问题吗? - rvictordelta
3
请勿在应使用 === 的情况下使用 == - Alnitak
5个回答

12
你可以使用Array#reduce方法。

var data = [{prop1:"abc",prop2:"qwe"},{prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"}];

console.log(
  data.reduce(function(arr, e, i) {
    if (e.prop1 == 'abc') arr.push(i);
    return arr;
  }, [])
)

// with ES6 arrow syntax
console.log(
  data.reduce((arr, e, i) => ((e.prop1 == 'abc') && arr.push(i), arr), [])
)


使用简单的for循环

var data = [{prop1:"abc",prop2:"qwe"},{prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"}];

var res = [];

for (var i = 0; i < data.length; i++) {
  if (data[i].prop1 == 'abc') res.push(i);
}

console.log(res)


或者使用Array#map方法与Array#filter一起使用(这不是一种高效的方法,因为需要两次迭代)。

var data = [{prop1:"abc",prop2:"qwe"},{prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"}];


console.log(
  data.map(function(e, i) {
    return i;
  }).filter(function(e) {
    return data[e].prop1 == 'abc';
  })
)

// With ES6 arrow syntax
console.log(
  data.map((_, i) => i).filter(e => data[e].prop1 == 'abc')
)


你使用 filter 的例子并不通用。 - str
你可以使用ES5/ES6或其他语言编写,使用filter然后是map不起作用。在这种特定情况下,它产生了正确的结果,但仅因为条件匹配数组中的前x个项目。如果没有给出该条件,则它将无法正常工作。 - str
@str:谢谢,已更新答案 :) ... 我们只需要稍微变动一下顺序即可。 - Pranav C Balan
实际上,如果您将相同数量的操作分配到两个迭代中,则两个迭代并不会使其效率降低。filter/map 比自定义 reduce 函数更易读且通常更高效。 - Kyle Baker

1
您可以使用reduce函数。

var array = [{ prop1: "abc", prop2: "qwe" }, 
             { prop1: "abc", prop2: "yutu" }, 
             { prop1: "xyz", prop2: "qwrq" }];

var indexes = array.reduce((a, c, i/*Current index*/) => {
  if (c.prop1 == "abc") a.push(i); //Add the found index.
  return a;
}, []/*Accumulator to store the found indexes.*/);

console.log(indexes);

资源

1
您可以使用array.prototype.reduce简写if来使它只需一行代码:

var arr = [ {prop1:"abc",prop2:"qwe"}, {prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"} ];

var indexes = arr.reduce((m, e, i) => (e.prop1 === 'abc' && m.push(i), m), []);
console.log(indexes);


你能解释一下这个逗号和 m 是什么意思吗?(e.prop1 === 'abc' && m.push(i), m) - berkan
1
@berkan 这是 JavaScript 的 逗号运算符。它确保 e.prop1 === 'abc' && m.push(i) 总是被执行,并且 m 总是作为结果返回。可以重写为这个答案 - mishamosher

0
以下代码适用于我:

var data = [{prop1:"abc",prop2:"qwe"},{prop1:"abc",prop2:"yutu"},{prop1:"xyz",prop2:"qwrq"}]
var indexes = []

data.forEach((element, index)=>{
 if(element.prop1 =="abc"){
   indexes.push(index)
 }
});
    
console.log(indexes)


0

有一种纯函数式的方法可以做到这一点,但它并不特别高效,因为它需要对数组进行三次单独的线性扫描:

let indexes = array.map((e, i) => [i, e])
                   .filter(([i, e]) => predicate(e))
                   .map(([i, _]) => i);

在哪里

let predicate = e => e.prop1 === 'abc';

这个方法通过创建一个临时数组,在其中每个元素都是一个包含原始索引和元素的数组。然后它过滤掉谓词函数不为真的元素,最后将数组剥离,只保留索引。


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