Array.prototype.remove(item)

Bob Myers rtm at gol.com
Fri Nov 10 11:41:45 UTC 2017


What's wrong with this?

```js
function removeFromArray(array, pred) {
  let changed = false;
  let j = 0;

  for (elt of array) {
    if (pred(elt)) changed = true;
    else array[j++] = elt;
  }

  array.length = j;
  return changed;
}
```

Bob

On Fri, Nov 10, 2017 at 4:08 PM, Isiah Meadows <isiahmeadows at gmail.com>
wrote:

> I find myself frequently using this code to remove an item from an array:
>
> ```js
> var index = array.indexOf(item)
> if (index >= 0) array.splice(index, 1)
> ```
>
> That's nice, but there's a couple problems:
>
> 1. It only removes the first element, not all occurrences in the array
> (which is usually what you want).
> 2. I know of no engine that fuses those calls, and it'd be rather
> difficult to do so.
>
> My proposal is this: add a new `Array.prototype.remove(item)` method
> that basically does this:
>
> - Accept a list of items to remove, passed as arguments.
> - Remove all instances of those items from the array.
> - Return `true` if any entries were removed, `false` otherwise.
>
> And in the process, it should take care to do it in an optimized
> fashion, avoiding the overhead of allocation, excess reads/writes, and
> excess branching.
>
> In case you're curious why I'm not using `Set`, here's why that's
> ill-equipped in many cases:
>
> - Sets take up a *lot* more memory than arrays, by necessity.
> - Sets are stored typically in tree-like structures, making for poor
> iteration performance.
> - If you're frequently iterating, but infrequently adding/removing,
> these two will quickly kill your performance.
>
> It rarely comes up in day-to-day coding, but the difference is
> substantial when you're writing lower-level data structures and
> performance-sensitive code. It's probably down a similar vein to
> `Array.prototype.copyWithin`, which was pretty much designed for
> `memcpy` or `memmove`.
>
> Here would be a polyfill of what I'd like to propose (it uses a
> minimum of writes, by design, and it does everything in one pass):
>
> ```js
> if (typeof Array.prototype.remove !== "function") {
>     // Private utility
>     const includes = (items, itemLength, entry) => {
>         for (let j = 0; j < itemLength; j++) {
>             if (items[j] === entry) return true
>         }
>
>         return false
>     }
>
>     Array.prototype.remove = function (item) {
>         const oldLength = this.length
>         const newLength = arguments.length
>         // This is technically observably no different than
>         const items = [...arguments]
>         let newLength = 0
>
>         for (let i = 0; i < oldLength; i++) {
>             const entry = this[i]
>             if (includes(items, newLength, entry)) {
>                 let newLength = i++
>
>                 while (i !== list.length) {
>                     const entry = this[i]
>                     if (!includes(items, newLength, entry)) {
>                         this[newLength++] = entry
>                     }
>                     i++
>                 }
>
>                 this.length = newLength
>                 for (let i = newLength; i < oldLength; i++) delete this[i]
>                 return true
>             }
>         }
>
>         return false
>     }
> }
> ```
>
> If the variadic version wasn't accepted, there's also the non-variadic
> version:
>
> ```js
> if (typeof Array.prototype.remove !== "function") {
>     Array.prototype.remove = function (item) {
>         const oldLength = this.length
>         let newLength = 0
>
>         for (let i = 0; i < oldLength; i++) {
>             const entry = this[i]
>             if (entry === item) {
>                 let newLength = i++
>
>                 while (i !== list.length) {
>                     const entry = this[i]
>                     if (entry !== item) this[newLength++] = entry
>                     i++
>                 }
>
>                 this.length = newLength
>                 for (let i = newLength; i < oldLength; i++) delete this[i]
>                 return true
>             }
>         }
>
>         return false
>     }
> }
> ```
>
> -----
>
> Isiah Meadows
> me at isiahmeadows.com
>
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> www.isiahmeadows.com
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171110/e61ea2f8/attachment-0001.html>


More information about the es-discuss mailing list