Array.prototype.toggle
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); // ???
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]
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.
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
?
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:
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.
I would not be interested in adding any more mutating methods to
Array.prototype, ever. I'd suggest using .filter
for this.
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)
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.
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]
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.
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.
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]