Array.prototype.toggle

# manuelbarzi (4 years ago)

just a proposal to provide this functionality into array, allowing to add / remove items in a toggling mechanism shortcut, avoiding the need to do traversing to locate the indexes and remove them next (i.e. by means of a polyfill or any other approach).

[1, 2, 3, 2, 1].toggle(1) // mutates the original array removing 1,
resulting in [2, 3, 2]
# Scott Rudiger (4 years ago)

Array.prototype.filter seems more versatile (although it doesn't mutate the original array) since it removes elements based on a function:

[1, 2, 3, 2, 1].filter(n => n !== 1); // [2, 3, 2]

Since the method is named toggle, what happens when you call it on the same array twice? Do you get the removed elements back?

const arr = [1, 2, 3, 2, 1].toggle(1) // mutates the original array
removing 1, resulting in [2, 3, 2]
arr.toggle(1); // ???
# manuelbarzi (4 years ago)

calling it again would just apply the same mechanism => "do this element

already exist? "remove it" : "add it". in the example, it would just add 1 at the end of array (i.e. just a push), calling it the second time.

``js const a = [1, 2, 3, 2, 1].toggle(1) // mutates the original array removing 1 => [2, 3, 2]

a.toggle(1); // mutates the original array adding 1 => [2, 3, 2, 1]

# Claude Pache (4 years ago)

Le 7 févr. 2020 à 13:23, manuelbarzi <manuelbarzi at gmail.com> a écrit :

calling it again would just apply the same mechanism => "do this element already exist? "remove it" : "add it". in the example, it would just add 1 at the end of array (i.e. just a push), calling it the second time.

Probably Array.prototype.remove would be a more appropriate name for what you suggest.

The DOMTokenList array-like interface has such a remove method (and some others):

developer.mozilla.org/en-US/docs/Web/API/DOMTokenList, developer.mozilla.org/en-US/docs/Web/API/DOMTokenList

Although, in situations where I am in a need of a remove method, I tend to use a Set instead of an Array.

# Claude Pache (4 years ago)

Le 7 févr. 2020 à 14:52, Claude Pache <claude.pache at gmail.com> a écrit :

Le 7 févr. 2020 à 13:23, manuelbarzi <manuelbarzi at gmail.com <mailto:manuelbarzi at gmail.com>> a écrit :

calling it again would just apply the same mechanism => "do this element already exist? "remove it" : "add it". in the example, it would just add 1 at the end of array (i.e. just a push), calling it the second time.

Probably Array.prototype.remove would be a more appropriate name for what you suggest.

Sorry, I somewhat misread your message. So:

The DOMTokenList array-like interface has a toggle method, and some others like add, remove, etc.

developer.mozilla.org/en-US/docs/Web/API/DOMTokenList, developer.mozilla.org/en-US/docs/Web/API/DOMTokenList

Although, as I said, in such situations, I tend to use a Set instead of an Array.

Maybe it would make sense to add a toggle method to Set.prototype?

# Augusto Moura (4 years ago)

To me this is more a use case for using Set instead of arrays, the support is already great and it can be polyfilled. Set is the right data structure to verify if some element is or is not in a collection

Em sex., 7 de fev. de 2020 às 08:49, manuelbarzi <manuelbarzi at gmail.com>

escreveu:

# manuelbarzi (4 years ago)

many things that already provide array could be polyfilled, and probably many were polyfills before. it's not about to discuss that, but the chance to integrate it in array as a useful feature if most agree it could be so.

# Jordan Harband (4 years ago)

I would not be interested in adding any more mutating methods to Array.prototype, ever. I'd suggest using .filter for this.

# Herby Vojčík (4 years ago)

On 7. 2. 2020 13:11, Scott Rudiger wrote:

Array.prototype.filter seems more versatile (although it doesn't mutate the original array) since it removes elements based on a function:

[1, 2, 3, 2, 1].filter(n => n !== 1); // [2, 3, 2]

But what if one wants to mutate in-place. Would this work?

Object.assign(arr, arr.filter(n => n !== 1))

If not, maybe there can be

aCollection.replaceWith(anIterable)

# Dalrymple, Joseph (4 years ago)

I agree. A Set is designed for this specific use case and has the methods you're looking for already built-in to it. I'm not sure that adding this would provide any significant value.

# Scott Rudiger (4 years ago)

I believe this wouldn't result in the OP's desired results since the filtered array is no longer the same length as the original array:

var toggle = (arr, el) => Object.assign(arr, arr.filter(n => n !== el));

toggle([1, 2, 3, 2, 1], 1); // [2, 3 ,2, 2, 1]

Here's a helper function that would work (and also push the element if it's not included in the original array):

var toggle = (arr, el) => {

var len = arr.length;

for (var i = 0; i < arr.length; i++)
if (arr[i] === el)
arr.splice(i--, 1);

if (arr.length === len)
arr.push(el);

return arr;
};

var a = toggle([1, 2, 3, 2, 1], 1); // mutates the original array removing
1 => [2, 3, 2]

toggle(a, 1); // mutates the original array adding 1 => [2, 3, 2, 1]
# manuelbarzi (4 years ago)

no intention in this proposal to discuss the how, but just the what, as i assume everybody here knows how to implement it in a polyfill, single function or any other approach. the proposal just goes on the idea that "hey, we have already semantic things like some, every, etc... in array, wouldn't it be useful to have the toggle too? which in my case i found using and reusing in various projects already. how about you, guys?" then if there is enough quorum, just thinking about integrating it or not. that's all. thank you.

# Steve Fink (4 years ago)

If you're looking for data points: I have never wanted exactly this, and would find it a pretty bizarre thing to find in the standard library. The most similar thing I've wanted would be to toggle something's presence in a Set. Far more often than that, I've wanted something like upsert or setdefault. Far more often than that, I've wanted Map.prototype.get with a default value, though probably ?? covers that scenario well enough now.

One reason why toggle's inclusion would seem weird to me is that it's not clear to me whether it should remove all copies, or just the first (so you'd need to toggle N times to clear out an array with N copies). Nor is it obvious why an added-by-toggle element should be pushed onto the end as opposed to somewhere else in the list (eg if I had a sorted array, I'd probably expect it to be in the middle.)  The main reason, though, is that it feels rather niche.