Skip to content
This repository was archived by the owner on Jun 7, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,75 @@
# [proposal-array-find-right](https://kingwl.github.io/proposal-array-find-right/index.html)

Proposal for a `.findRight()` method on array.
Proposal for `.findRight()` and `.findIndex` methods on array.

## Motivation

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 out customized way.
And we also has `Array.prototype.find`, `Array.prototype.findIndex` to find some element or index who in the array in out 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.
1. **unnecessary reverse.**
2. **`Array.prototype.reverse` is not immutable.**

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

As the result the third issue:
As the result, the third issue:

3. unnecessary spread
3. **unnecessary spread**

So, perhaps we need `Array.prototype.findRight`.
For `.findIndex()`, you must have much additional operations (re-calculate index and handle the `-1` ) for the result of `[...arr].reverse().findIndex()`.

As the result, the fourth issue:

4. **complex index calculate**

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

## Core features

Add `Array.prototype.findRight`.
Add `Array.prototype.findRight` and `Array.prototype.findIndexRight`.

And we could use that like the [(Array.prototype.find)](https://www.ecma-international.org/ecma-262/11.0/index.html#sec-array.prototype.find) but from the end to be start.
And we could use that like the [Array.prototype.find](https://www.ecma-international.org/ecma-262/11.0/index.html#sec-array.prototype.find) and [Array.prototype.findIndex](https://www.ecma-international.org/ecma-262/11.0/index.html#sec-array.prototype.findindex) but from the end to be start.

eg:

```javascript
const array = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];

array.find(n => n.value % 2 === 1); // { value: 1 }
array.findIndex(n => n.value % 2 === 1); // 0

// Before the proposal
// ======== Before the proposal ===========

// find
[...array].reverse().find(n => n.value % 2 === 1); // { value: 3 }

// In the proposal
// findIndex
array.length - 1 - [...array].reverse().findIndex(n => n.value % 2 === 1); // 2
array.length - 1 - [...array].reverse().findIndex(n => n.value === 42); // should be -1, but 4

// ======== In the proposal ===========
// find
array.findRight(n => n.value % 2 === 1); // { value: 3 }

// findIndex
array.findIndexRight(n => n.value % 2 === 1); // 2
array.findIndexRight(n => n.value === 42); // -1

```

## Related

- [Array.prototype.reduceRight](https://www.ecma-international.org/ecma-262/11.0/index.html#sec-array.prototype.reduceright)
- [lodash.findLast](https://lodash.com/docs/4.17.15#findLast)
- [lodash.findLastIndex](https://lodash.com/docs/4.17.15#findLastIndex)
- [ramda.findLast](https://ramdajs.com/docs/#findLast)

- [ramda.findLastIndex](https://ramdajs.com/docs/#findLastIndex)
- [@extra-array/find-right](https://www.npmjs.com/package/@extra-array/find-right)

9 changes: 7 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1845,12 +1845,17 @@
display: none;
}
}
</style></head><body><div id="menu-toggle">☰</div><div id="menu-spacer"></div><div id="menu"><div id="menu-search"><input type="text" id="menu-search-box" placeholder="Search..."><div id="menu-search-results" class="inactive"></div></div><div id="menu-pins"><div class="menu-pane-header">Pins</div><ul id="menu-pins-list"></ul></div><div class="menu-pane-header">Table of Contents</div><div id="menu-toc"><ol class="toc"><li><span class="item-toggle-none"></span><a href="#sec-demo-clause" title="Array.prototype.findRight"><span class="secnum">1</span> Array.prototype.findRight</a></li><li><span class="item-toggle-none"></span><a href="#sec-copyright-and-software-license" title="Copyright &amp; Software License"><span class="secnum">A</span> Copyright &amp; Software License</a></li></ol></div></div><div id="spec-container"><h1 class="version first">Stage 0 Draft / November 10, 2020</h1><h1 class="title">Proposal Array.prototype.findRight</h1>
</style></head><body><div id="menu-toggle">☰</div><div id="menu-spacer"></div><div id="menu"><div id="menu-search"><input type="text" id="menu-search-box" placeholder="Search..."><div id="menu-search-results" class="inactive"></div></div><div id="menu-pins"><div class="menu-pane-header">Pins</div><ul id="menu-pins-list"></ul></div><div class="menu-pane-header">Table of Contents</div><div id="menu-toc"><ol class="toc"><li><span class="item-toggle-none"></span><a href="#sec-demo-clause" title="Array.prototype.findRight"><span class="secnum">1</span> Array.prototype.findRight</a></li><li><span class="item-toggle-none"></span><a href="#sec-copyright-and-software-license" title="Copyright &amp; Software License"><span class="secnum">A</span> Copyright &amp; Software License</a></li></ol></div></div><div id="spec-container"><h1 class="version first">Stage 0 Draft / November 11, 2020</h1><h1 class="title">Proposal Array.prototype.findRight</h1>

<emu-clause id="sec-demo-clause">
<h1><span class="secnum">1</span> Array.prototype.findRight</h1>
<p>The find method is called with one or two arguments, predicate and thisArg.</p>
<p>The findRight method is called with one or two arguments, predicate and thisArg.</p>
<p>When the findRight method is called, the following steps are taken:</p>
<emu-alg><ol><li>Let O be ?&nbsp;<emu-xref aoid="ToObject" id="_ref_0"><a href="https://tc39.es/ecma262/#sec-toobject">ToObject</a></emu-xref>(this value).</li><li>Let idx be ?&nbsp;<emu-xref aoid="LengthOfArrayLike" id="_ref_1"><a href="https://tc39.es/ecma262/#sec-lengthofarraylike">LengthOfArrayLike</a></emu-xref>(O).</li><li>If <emu-xref aoid="IsCallable" id="_ref_2"><a href="https://tc39.es/ecma262/#sec-iscallable">IsCallable</a></emu-xref>(predicate) is false, throw a TypeError exception.</li><li>Repeat, while idx &gt;= 0<ol><li>Let Pi be !&nbsp;<emu-xref aoid="ToString" id="_ref_3"><a href="https://tc39.es/ecma262/#sec-tostring">ToString</a></emu-xref>(idx).</li><li>Let iValue be ?&nbsp;<emu-xref aoid="Get" id="_ref_4"><a href="https://tc39.es/ecma262/#sec-get-o-p">Get</a></emu-xref>(O, Pi).</li><li>Let testResult be !&nbsp;<emu-xref aoid="ToBoolean" id="_ref_5"><a href="https://tc39.es/ecma262/#sec-toboolean">ToBoolean</a></emu-xref>(? <emu-xref aoid="Call" id="_ref_6"><a href="https://tc39.es/ecma262/#sec-call">Call</a></emu-xref>(predicate, thisArg, « iValue, idx, O »)).</li><li>If testResult is true, return iValue.</li><li>Set idx to idx - 1</li></ol></li><li>Return undefined</li></ol></emu-alg>
<h1>Array.prototype.findIndexRight</h1>
<p>The findIndexRight method is called with one or two arguments, predicate and thisArg.</p>
<p>When the findIndexRight method is called with one or two arguments, the following steps are taken:</p>
<emu-alg><ol><li>Let O be ?&nbsp;<emu-xref aoid="ToObject" id="_ref_7"><a href="https://tc39.es/ecma262/#sec-toobject">ToObject</a></emu-xref>(this value).</li><li>Let idx be ?&nbsp;<emu-xref aoid="LengthOfArrayLike" id="_ref_8"><a href="https://tc39.es/ecma262/#sec-lengthofarraylike">LengthOfArrayLike</a></emu-xref>(O).</li><li>If <emu-xref aoid="IsCallable" id="_ref_9"><a href="https://tc39.es/ecma262/#sec-iscallable">IsCallable</a></emu-xref>(predicate) is false, throw a TypeError exception.</li><li>Repeat, while idx &gt;= 0<ol><li>Let Pi be !&nbsp;<emu-xref aoid="ToString" id="_ref_10"><a href="https://tc39.es/ecma262/#sec-tostring">ToString</a></emu-xref>(idx).</li><li>Let iValue be ?&nbsp;<emu-xref aoid="Get" id="_ref_11"><a href="https://tc39.es/ecma262/#sec-get-o-p">Get</a></emu-xref>(O, Pi).</li><li>Let testResult be !&nbsp;<emu-xref aoid="ToBoolean" id="_ref_12"><a href="https://tc39.es/ecma262/#sec-toboolean">ToBoolean</a></emu-xref>(? <emu-xref aoid="Call" id="_ref_13"><a href="https://tc39.es/ecma262/#sec-call">Call</a></emu-xref>(predicate, thisArg, « iValue, idx, O »)).</li><li>If testResult is true, return idx.</li><li>Set idx to idx - 1</li></ol></li><li>Return -1</li></ol></emu-alg>
</emu-clause><emu-annex id="sec-copyright-and-software-license">
<h1><span class="secnum">A</span> Copyright &amp; Software License</h1>

Expand Down
18 changes: 17 additions & 1 deletion spec.emu
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ contributors: Wenlu Wang

<emu-clause id="sec-demo-clause">
<h1>Array.prototype.findRight</h1>
<p>The find method is called with one or two arguments, predicate and thisArg.</p>
<p>The findRight method is called with one or two arguments, predicate and thisArg.</p>
<p>When the findRight method is called, the following steps are taken:</p>
<emu-alg>
1. Let O be ? ToObject(this value).
2. Let idx be ? LengthOfArrayLike(O).
Expand All @@ -24,4 +25,19 @@ contributors: Wenlu Wang
5. Set idx to idx - 1
5. Return undefined
</emu-alg>
<h1>Array.prototype.findIndexRight</h1>
<p>The findIndexRight method is called with one or two arguments, predicate and thisArg.</p>
<p>When the findIndexRight method is called with one or two arguments, the following steps are taken:</p>
<emu-alg>
1. Let O be ? ToObject(this value).
2. Let idx be ? LengthOfArrayLike(O).
3. If IsCallable(predicate) is false, throw a TypeError exception.
4. Repeat, while idx >= 0
1. Let Pi be ! ToString(idx).
2. Let iValue be ? Get(O, Pi).
3. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « iValue, idx, O »)).
4. If testResult is true, return idx.
5. Set idx to idx - 1
5. Return -1
</emu-alg>
</emu-clause>