简体   繁体   English

按特定条件查找数组内元素的最后一个索引

[英]Find last index of element inside array by certain condition

Let's say I have an array of objects:假设我有一个对象数组:

[
  {'a': 'something', 'b':12},
  {'a': 'something', 'b':12},
  {'a': 'somethingElse', 'b':12},
  {'a': 'something', 'b':12},
  {'a': 'somethingElse', 'b':12}
]

What would be the most cleanest way to get the last index of the element where a has the value 'something'.获取元素的最后一个索引的最干净的方法是什么,其中 a 的值为“某物”。 In this case 3. Is there any way to avoid loops...在这种情况下 3. 有什么办法可以避免循环...

Here's a reusable typescript version which mirrors the signature of the ES2015 findIndex function:这是一个可重用的打字稿版本,它反映了 ES2015 findIndex 函数的签名:

/**
* Returns the index of the last element in the array where predicate is true, and -1
* otherwise.
* @param array The source array to search in
* @param predicate find calls predicate once for each element of the array, in descending
* order, until it finds one where predicate returns true. If such an element is found,
* findLastIndex immediately returns that element index. Otherwise, findLastIndex returns -1.
*/
export function findLastIndex<T>(array: Array<T>, predicate: (value: T, index: number, obj: T[]) => boolean): number {
    let l = array.length;
    while (l--) {
        if (predicate(array[l], l, array))
            return l;
    }
    return -1;
}

You can use findIndex to get index.您可以使用findIndex来获取索引。 This will give you first index, so you will have to reverse the array.这将为您提供第一个索引,因此您必须反转数组。

 var d = [{'a': "something", 'b':12}, {'a': "something", 'b':12}, {'a': "somethingElse", 'b':12}, {'a': "something", 'b':12}, {'a': "somethingElse", 'b':12}] function findLastIndex(array, searchKey, searchValue) { var index = array.slice().reverse().findIndex(x => x[searchKey] === searchValue); var count = array.length - 1 var finalIndex = index >= 0 ? count - index : index; console.log(finalIndex) return finalIndex; } findLastIndex(d, 'a', 'something') findLastIndex(d, 'a', 'nothing')

let newArray = yourArray.filter((each)=>{
    return (each.a === something)
});
newArray[newArray.length-1];

You can also do你也可以这样做

let reversedArray = yourArray.reverse();
reversedArray.find((each)=>{return each.a === something})

You could iterate from the end and exit the loop if found.如果找到,您可以从最后迭代并退出循环。

 var data = [{ a: 'something', b: 12 }, { a: 'something', b: 12 }, { a: 'somethingElse', b: 12 }, { a: 'something', b: 12 }, { a: 'somethingElse', b: 12 }], l = data.length; while (l--) { if (data[l].a ==='something') { break; } } console.log(l);

Reversing the array did not sound very straightforward to me, so my solution to my very similar case was using map() and lastIndexOf() :反转数组对我来说听起来不是很简单,所以我对非常相似的情况的解决方案是使用map()lastIndexOf()

var lastIndex = elements.map(e => e.a).lastIndexOf('something');

Upd.: this answer from the dupe post makes it even better with map(cond).lastIndexOf(true)更新:来自欺骗帖子的这个答案使用map(cond).lastIndexOf(true)使它变得更好

Upd.: though this is not the most efficient solution, as we have to always traverse all array, whereas if we ran from end, we could end search the moment we found first match (@nico-timmerman's answer).更新:虽然这不是最有效的解决方案,因为我们必须始终遍历所有数组,而如果我们从末尾运行,我们可以在找到第一个匹配项的那一刻结束搜索(@nico-timmerman 的答案)。

I wonder why lots of people would like to always avoid loops nowadays.我想知道为什么现在很多人都想总是避免循环。 They are just as natural structures as if s and pure sequence of code lines.它们都一样自然结构为if S和代码行纯序列。 To avoid repeating yourself, write a function for it, what you even could add to Array.prototype .为避免重复,请为它编写一个函数,您甚至可以将其添加到Array.prototype The following is a simple example, not tested, just for the idea.下面是一个简单的例子,未经测试,仅供参考。

For getting the index获取索引

Array.prototype.lastIndex = function(cond) {
  if (!this.length) return -1;
  if (!cond) return this.length-1;

  for (var i=this.length-1; i>=0; --i) {
    if (cond(this[i])) return i;
  }

  return -1;
}

Or for elements directly或者直接用于元素

Array.prototype.lastOrDefault = function(cond, defaultValue) {
  if (!this.length) return defaultValue;
  if (!cond) return this[this.length-1];

  for (var i=this.length-1; i>=0; --i) {
    if (cond(this[i])) return this[i];
  }

  return defaultValue;
}

Usage example:用法示例:

myArr = [1,2,3,4,5];
var ind1 = myArr.lastIndex(function(e) { return e < 3; }); 
var num2 = myArr.lastOrDefault(function(e) { return e < 3; });
var num8 = myArr.lastOrDefault(function(e) { return e > 6; }, /* explicit default */ 8);

Please take a look at this method.请看看这个方法。

 var array=[{a: 'something', b:12}, {a: 'something', b:12}, {a: 'somethingElse', b:12}, {a: 'something', b:12}, {a: 'somethingElse', b:12} ]; console.log(array.filter(function(item){ return item.a=='something'; }).length);

这是我用来获取最后一个活动元素的内容:

return this._scenarios.reverse().find(x => x.isActive);

You could use Lodash:你可以使用 Lodash:

import findLastIndex from "lodash/findLastIndex"

const data = [
  { a: 'something', b: 12 },
  { a: 'something', b: 12 },
  { a: 'somethingElse', b: 12 },
  { a: 'something', b: 12 },
  { a: 'somethingElse', b: 12 },
]

const lastIndex = findLastIndex(data, v => v.a === "something")

在 ES6 中这样的东西怎么样:

  arr.indexOf(arr.filter(item => item.a === 'something').pop())

这是我使用的:

const lastIndex = (items.length -1) - (items.reverse().findIndex(el=> el.a === "something"))

First, this is not an array of objects but an array of arrays.首先,这不是一个对象数组,而是一个数组数组。 An array of objects would look like this:对象数组如下所示:

[{'a': something, 'b':12},
{'a': something, 'b':12},
{'a': somethingElse, 'b':12},
{'a': something, 'b':12},
{'a': somethingElse, 'b':12}]

Generally it's a good practice to use object syntax when you use non-numeric indices.通常,在使用非数字索引时使用对象语法是一种很好的做法。

Second, to answer your question you can just use a reverse loop:其次,要回答您的问题,您可以使用反向循环:

for(let i=(arr.length - 1); i>=0; i--){
    if(arr[i].a === "something"){
        index = i;
        break;
    }
}
var arr = [
   {'a': 'something', 'b':12},
   {'a': 'something', 'b':12},
   {'a': 'somethingElse', 'b':12},
   {'a': 'something', 'b':12},
   {'a': 'somethingElse', 'b':12}
];

var item_count = 0;
var traverse_count = 0;
var last_item_traverse_count = 0;    
arr = arr.reverse();

arr.filter(function(element) {
   traverse_count += 1;
   if(item_count < 1 && element.a == 'something') {
       last_item_traverse_count = traverse_count;
       item_count += 1;
       return true;
   }

   return false;
});

var item_last_index = arr.length - last_item_traverse_count;

console.log(item_last_index);

I hope this code definitely works.我希望这段代码绝对有效。 The code may not follow naming conventions.代码可能不遵循命名约定。 I'm sorry about that.我很抱歉。 You can just name those variables however you want.您可以随意命名这些变量。

The cleanest way i found was using a single reduce.我发现的最干净的方法是使用单个减少。 No need to reverse the array or using multiple loops无需反转数组或使用多个循环

const items = [
  {'a': 'something', 'b': 12},
  {'a': 'something', 'b': 12},
  {'a': 'somethingElse', 'b': 12},
  {'a': 'something', 'b': 12},
  {'a': 'somethingElse', 'b': 12}
];

function findLastIndex(items, callback) {
  return items.reduce((acc, curr, index) => callback(curr) ? index : acc, 0);
}

console.log(findLastIndex(items, (curr) => curr.a === "something"));

You can use reverse and map together to prevent from mutating the original array.您可以同时使用 reverse 和 map 来防止改变原始数组。

var arr = [{'a': 'something', 'b':12},
{'a': 'something', 'b':12},
{'a': 'somethingElse', 'b':12},
{'a': 'something', 'b':12},
{'a': 'somethingElse', 'b':12}];

var index = arr.length - 1 - arr.map(x => x)
   .reverse()
   .findIndex(x => (x.a === 'something'))
if (index === arr.length) {
  index = -1;
}

 const arrSome = [{'a': 'something', 'b':12}, {'a': 'something', 'b':12}, {'a': 'somethingElse', 'b':12}, {'a': 'something', 'b':12}, {'a': 'somethingElse', 'b':12}] const lastIndex = arrSome.reverse().findIndex(el=> el.a == 'something');//? let index; if (~lastIndex) { index =arrSome.length - lastIndex; } else { index = -1 } console.log(index)

You can use Math.max apply to the array that match your condition with Array.prototype.map()您可以使用Math.max应用于与Array.prototype.map()匹配条件的数组

like this example像这个例子

private findLastIndex() {
    const filter = this.myArray.map((t, index) => {
      if (
        // your condition
      ) {
        return index;
      } else {
        return -1;
      }
    });

    return Math.max.apply(null, filter);
  }

Here's a solution using no (manual) loops, and without mutating the calling array:这是一个不使用(手动)循环且不改变调用数组的解决方案:

 const arr = [ {'a': 'something', 'b': 12}, {'a': 'something', 'b': 12}, {'a': 'somethingElse', 'b': 12}, {'a': 'something', 'b': 12}, {'a': 'somethingElse', 'b': 12} ]; function findLastIndex(arr, callback, thisArg) { return (arr.length - 1) - // Need to subtract found, backwards index from length arr.reduce((acc, cur) => [cur, ...acc], []) // Get reversed array .findIndex(callback, thisArg); // Find element satisfying callback in rev. array } console.log(findLastIndex(arr, (e) => ea === "something"));

Reference:参考:

It should be noted that the reducer used here is vastly outperformed by arr.slice().reverse() , as used in @Rajesh's answer .应该注意的是,这里使用的 reducer 大大优于@Rajesh's answer 中使用的arr.slice().reverse()

You can achieve this using reverse and findIndex .您可以使用reversefindIndex来实现这findIndex

** Soon, you'll be able to use findLastIndex which is currently in stage 3. ** 很快,您将能够使用当前处于第 3 阶段的findLastIndex

 var d = [{'a': "something", 'b':12}, {'a': "something", 'b':12}, {'a': "somethingElse", 'b':12}, {'a': "something", 'b':12}, {'a': "somethingElse", 'b':12}] const lastIdx = d.reverse().findIndex(n => na === 'something'); console.log(lastIdx);

findLastIndex - https://github.com/tc39/proposal-array-find-from-last findLastIndex - https://github.com/tc39/proposal-array-find-from-last

findIndex - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex findIndex - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

reverse - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse反向- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

Simple and fast:简单快速:

const arr = [
  {'a': 'something', 'b': 12},
  {'a': 'something', 'b': 12},
  {'a': 'somethingElse', 'b': 12},
  {'a': 'something', 'b': 12},
  {'a': 'somethingElse', 'b': 12}
];

let i = arr.length;
while(i--) if (arr[i] === 'something') break;

console.log(i);  //last found index or -1

Update 27 October 2021 2021 年 10 月 27 日更新

You can now use findLastIndex :您现在可以使用findLastIndex

const array = [
  {'a': 'something', 'b':12},
  {'a': 'something', 'b':12},
  {'a': 'somethingElse', 'b':12},
  {'a': 'something', 'b':12},
  {'a': 'somethingElse', 'b':12}
];

const last_index = array.findLastIndex((item) => item.a === 'something');
// → 3

Read more here .在这里阅读更多。

You can just map the the list to a and then use lastIndexOf:您可以将列表映射到 a,然后使用 lastIndexOf:

 const array = [ {'a': 'something', 'b':12}, {'a': 'something', 'b':12}, {'a': 'somethingElse', 'b':12}, {'a': 'something', 'b':12}, {'a': 'somethingElse', 'b':12} ]; const result = array.map(({a}) => a).lastIndexOf('something'); console.log(result);

why not just get the length and use as a array pointer eg为什么不只是获取长度并用作数组指针,例如

var arr = [ 'test1', 'test2', 'test3' ];

then get the last index of the array by getting the length of the array and minus '1' since array index always starts at '0'然后通过获取数组的长度和减去 '1' 来获取数组的最后一个索引,因为数组索引总是从 '0' 开始

var last arrIndex = arr[arr.length - 1];

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

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