# Proposal for Array.prototype.findRight

**URL:** <https://es.discourse.group/t/proposal-for-array-prototype-findright/538>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [November 10, 2020, 6:12am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538 "2020-11-10T06:12:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 10, 2020, 6:12am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/1 "2020-11-10T06:12:16Z")

</div>

Find something from array is a very common pattern in development.

Now we have `Array.prototype.indexOf`, `Array.prototype.lastIndexOf` to find index of some `value` in the array.

And we also has `Array.prototype.find` to find some element who in the array in customized way.

But There’s not a way to allow us find something `from the end to the start ` of array in customized way.

`[].reverse().find()` is work. But there’s two issues:

1. unnecessary reverse.
2. `Array.prototype.reverse` is not immutable.

You have to write the `findRight` in your codebase or `[...[]].reverse().find()`.

As the result the third issue:

1. unnecessary spread

So, perhaps we need `Array.prototype.findRight`.

And I create a draft proposal [https://github.com/Kingwl/proposal-array-find-right](https://github.com/Kingwl/proposal-array-find-right).

Thanks!

---

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 11, 2020, 8:10am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/2 "2020-11-11T08:10:50Z")

</div>

Added Array.prototype.findIndexRight. Updated in the repo.

---

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 11, 2020, 12:59pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/3 "2020-11-11T12:59:30Z")

</div>

Added `%TypedArray%.prototype.findRight` and `%TypedArray%.prototype.findIndexRight`.

Updated in the repo.

---

<div class="post-metadata">

**Author:** ![claudepache](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudepache/32/236_2.png) [@claudepache](https://es.discourse.group/u/claudepache)\
**Post date:** [November 12, 2020, 10:54am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/4 "2020-11-12T10:54:17Z")

</div>

The method names should use “last”, not “right” (in line with `Array.prototype.lastIndexOf`).

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [November 12, 2020, 4:20pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/5 "2020-11-12T16:20:10Z")

</div>

Or “end”, in line with String.prototype.trimEnd/padEnd?

---

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 12, 2020, 5:21pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/6 "2020-11-12T17:21:53Z")

</div>

We have `trimStart`,`trimEnd`, `padStart`, `padEnd`.

And we have `find`, `findIndex`.

But we don't have something like `findStart` or `findIndexStart`.

And there's no `first` or `last` existed yet.

Currently, we have `reduce` and `reduceRight`.

So the \*\*\*Right might be a solution for a method that we already have.

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 14, 2020, 11:44pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/7 "2020-11-14T23:44:29Z")

</div>

The current APIs you've listed depend on being left or right.

Yours does not.

In order for this to be useful, you should describe a use-case where it is probabilistically higher to find an element starting from the end. In particular, not only does it has to have that... the use case should also explain why using `reverse` would be bad.

IMO, such a use case will be very difficult to find. If such a "probabilistically higher on the right" case existed, then I would probably **want** to reverse the array, since the unreversed ordering is useless.

Logically, this would imply the only use case is when there is a high probability of finding item 1 from the right, then after finding, there is a high probability of finding item 2 on the left...and so on so forth. But this alternating construct implies that there is uniform probability of finding item n in the array, so `findRight` is useless since we can just use `find` and we go back to having no use case.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [November 15, 2020, 11:26am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/8 "2020-11-15T11:26:43Z")

</div>

@jun-sheaf You seem to be missing the case where `findRight` finds a _different_ item than `find`, not just the same item with less comparisons.

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 15, 2020, 12:03pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/9 "2020-11-15T12:03:34Z")

</div>

I am actually missing two cases: Single use and duplicate items. The latter implies fairly bad structuring of data.

The only reasonable case seems to be single use.

---

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 15, 2020, 3:04pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/11 "2020-11-15T15:04:48Z")

</div>

Thanks for the review. I think my description may not be clear enough.

1. As @bergus said. `findRight` finds a _different_ item than `find`.  
The duplicate items may means the **mapping** of some items is duplicated. Not literally duplicated.  
One case is:  
a. You have a list and a current index that you should show the result of the index.  
b. Each item may have two status: `enabled` and `disabled`.  
c. You have two action: `Jump to prev enabled item` and `Jump to next enabled item`.  
d. The action will modified the current index.  
You could:  
a. `slice(0, currentIndex)` or `slice(currentIndex + 1)` (Maybe COW, little overhead)  
b. `findRightIndex` on slice of `[0, currentIndex]` or `findIndex` on slice of `[currentIndex + 1]`  
Or you could do it without findRight on find prev:  
a. create `Map<item. index>`  
b. `slice(0, currentIndex)`  
c. `[...slice].reverse() ` (At least a copy and a reverse iteration)  
d. `find` on reversed slice  
e. indexMap.get(item) || -1

It's a bit complicated and maybe expensive.  
If you have a huge list, And the operation happens when you are rendering(eg: React).  
That may not caused a good experience.

Actually. That is a simple version of a scene that happened in my recent job. That's why I have the idea of the proposal.

1. I have searched on github with keyword 'findRight'(and 'findLast'). The result shows many project has implemented their own `findRight` (or 'findLast'). And there's some references of lodash or ramda.

Thanks!

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 15, 2020, 5:41pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/12 "2020-11-15T17:41:03Z")

</div>

When I meant duplicate items, I meant duplicate with regard to the predicate. In particular, if they are different items, then you should `find` based on their differences. Also,

1. if there is an ordering, then both `find` and `findRight` are horrible. You should use binary search.
2. if there is no ordering, then assuming uniform probability (non-uniform probability was explained previously), then using `find` or `findRight` won't matter. Both have equal probability of finding an item.

Now regarding your use case, you have yet to address any issue.

1. Why do you need to copy then reverse. Who cares if the slice is reversed, you only need it for finding the index.
2. After you reverse, just `findIndex` and just subtract that from `currentIndex`. What is with the map?

The point of this conversation is that you give me a proper algorithmic analysis of the situation. You are asking for an algorithm after all.

In any case, if you do the math, you would understand that reverse takes `n/2` operations and a find for an object on the reversed object would take `n/2` operations for an object on the first half of the reversed object. All in all, it would essentially be the same as using `find`.

In the end, your only real argument is that it is convenient (which I cannot/do not argue against; I like convenience).

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [November 15, 2020, 7:37pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/13 "2020-11-15T19:37:24Z")

</div>

Why would you want a binary search if there _is_ an ordering? If order matters, then the only kind of search you’d likely want do is “from 0, to length” or “from the length, to 0”.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [November 15, 2020, 8:13pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/14 "2020-11-15T20:13:09Z")

</div>

Thinking about this some more, I am against adding four methods `(Typed)Array.prototype.findLast(Index)` . Instead, the problem should be solved using iterators, which just need to become a bit more flexible to support this:

- the [_`ReverseIterable` interface_ proposal](https://github.com/leebyron/ecmascript-reverse-iterable) and
- the [_`Iterator` helpers_ proposal](https://github.com/tc39/proposal-iterator-helpers)

can achieve

```
const lastValue = array.values().reverse().find(…)
const [lastIndex, lastValue] = array.entries().reverse().find(…) ?? [-1, null]

```

while being simple and efficient.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [November 15, 2020, 8:17pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/15 "2020-11-15T20:17:03Z")

</div>

Regarding algorithmic analysis, the runtime complexity of finding an item in an array of `n` elements that is `k` removed from the last,

- using array `reverse` and `find` is `O(n + k)` whereas
- using a `findLast` method is `O(k)`

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 15, 2020, 9:06pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/16 "2020-11-15T21:06:50Z")

</div>

As in the elements are ordered, e.g. numbers.

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 15, 2020, 9:21pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/17 "2020-11-15T21:21:34Z")

</div>

Which is precisely why the operation is a convenience. One could just do reverse iteration.

By the way, although your analysis is correct, my point was `k` must be bounded by `n/2` in order for `findRight` to be useful. I could've stated at most `n/2` operations however...

---

<div class="post-metadata">

**Author:** ![Kingwl](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/kingwl/32/483_2.png) [@Kingwl](https://es.discourse.group/u/Kingwl)\
**Post date:** [November 16, 2020, 3:15am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/18 "2020-11-16T03:15:52Z")

</div>

@bergus

Okay. I agreed.

@jun-sheaf

> Why do you need to copy then reverse. Who cares if the slice is reversed, you only need it for finding the index.

My bad. slice does not need to spread again. But a readonly slice maybe not a copy. And if you call reverse, that will copy definitely.

> After you reverse, just `findIndex` and just subtract that from `currentIndex`. What is with the map?

because you must handle `-1` that you cannot subtract directly. (Okay, for convenience)

> if there is an ordering

There's an ordering but the ordering may not ordered by the predicate you want to find. So you cannot binary search.

---

<div class="post-metadata">

**Author:** ![Jonas\_Wilms](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jonas_wilms/32/189_2.png) [@Jonas\_Wilms](https://es.discourse.group/u/Jonas_Wilms)\
**Post date:** [November 17, 2020, 9:16pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/19 "2020-11-17T21:16:47Z")

</div>

`tickets.sort((a, b) => a.price - b.price); const mostExpensive = ticket.find(it => it.flight === 'TFS-HAM'), cheapest = ticket.findLast(it => it.flight === 'TFS-HAM');`

That would be a case were this would be useful, so in general arrays of objects were you have multiple properties were one could possibly sort by. For findIndex a possibly usecase would be something like:

`tickets.slice(tickets.findIndex(it => it.price >= 10), tickets.findLastIndex(it => it.price <= 20))`

so I'd say this fairly common.

---

<div class="post-metadata">

**Author:** ![jun-sheaf](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jun-sheaf/32/505_2.png) [@jun-sheaf](https://es.discourse.group/u/jun-sheaf)\
**Post date:** [November 19, 2020, 11:16pm UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/20 "2020-11-19T23:16:13Z")

</div>

Using two index pointers would have runtime `n`. Yours is `2n`. As I said, it’s a matter of convenience. I won’t argue against convenience.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [November 23, 2020, 3:08am UTC](https://es.discourse.group/t/proposal-for-array-prototype-findright/538/21 "2020-11-23T03:08:50Z")

</div>

The latter, searching for an item by condition via reverse iteration, amounts to 99% of reverse searching I do, and I find myself doing that more often than even `.lastIndexOf`. There's _lots_ of valid use cases for that, and they almost all are structured that way for performance reasons.

[Next page](https://es.discourse.group/t/proposal-for-array-prototype-findright/538.md?page=2)
