www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - delete an element from an array

reply =?ISO-8859-1?Q?Adam_Cig=E1nek?= <adam.ciganek gmail.com> writes:
Hello,

Is there a function in the standard library to delete an element from
an array (or range)? Something like:

  auto a = [1, 2, 3, 4, 5, 6];
  auto b = delete(a, 4);

  assert([1, 2, 3, 4, 6] == b);

I've noticed there is eliminate in std.algorithm, which seems to be
doing just that, but it's commented out.

It's not difficult to roll my own, (with the help of indexOf and
remove), but I thought that this is pretty common operation so it
should be in the standard library.


adam.
Oct 24 2010
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 24 Oct 2010 13:02:24 +0200, Adam Cig=C3=A1nek <adam.ciganek gmai=
l.com>  =

wrote:

 Hello,

 Is there a function in the standard library to delete an element from
 an array (or range)? Something like:

   auto a =3D [1, 2, 3, 4, 5, 6];
   auto b =3D delete(a, 4);

   assert([1, 2, 3, 4, 6] =3D=3D b);

 I've noticed there is eliminate in std.algorithm, which seems to be
 doing just that, but it's commented out.

 It's not difficult to roll my own, (with the help of indexOf and
 remove), but I thought that this is pretty common operation so it
 should be in the standard library.

std.algorithm has remove, which does what you want. -- = Simen
Oct 24 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Well, then use indexOf() to get the offset and remove() to remove the element.

But you must test the result value of indexOf, because it returns -1 (a signed value, probably an integer, not a signed word, so it may give troubles on 64 bit systems) when the item is missing. This is why Python has both a way to remove an item by index and by value. Bye, bearophile
Oct 24 2010
parent bearophile <bearophileHUGS lycos.com> writes:
spir:

 In my opinion, such non-obvious complications are good reasons to have
seemingly trivial operations implemented as builtin routines. (and should throw
error in case of failure)

std.algorithm.delete contains code like if(rEnd == range.length), so if you give it a signed integer coming from indexOf I think D converts it to unsigned... This is not good. In an enhancement request in Bugzilla you may ask for a function that removes the first instance of an item equal to the given item (if it's not present it may raise an exception or return a boolean false). In your bug report you may link Python docs where it shows both ways to remove an item by index or by value. If you don't want to write this enhancement request, I may do it myself. Bye, bearophile
Oct 24 2010
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 24/10/2010 12:24, Adam Cigánek wrote:
 remove removes element at a given offset. I want to remove element
 with a given value. This is example shows it better:

Your new example doesn't show it better, it's the only one you've given that shows it at all. What you had originally was auto a = [1, 2, 3, 4, 5, 6]; auto b = delete(a, 4); assert([1, 2, 3, 4, 6] == b); which shows the removal of the element at index 4, not the element with value 4. But there are further questions to be answered: - What do you want it to do if the value isn't in the array? Just return the original array, return a copy of the original array, or throw an exception? - What do you want it to do if the value is in the array more than once? Remove the first, remove the last, remove all of them, or pick one at random? Stewart.
Oct 24 2010
prev sibling next sibling parent =?ISO-8859-1?Q?Adam_Cig=E1nek?= <adam.ciganek gmail.com> writes:
remove removes element at a given offset. I want to remove element
with a given value. This is example shows it better:

  auto a =3D ["foo", "bar", "baz"];
  auto b =3D delete(a, "bar");

  assert(["foo", "baz"] =3D=3D b);


adam.

2010/10/24 Simen kjaeraas <simen.kjaras gmail.com>:
 On Sun, 24 Oct 2010 13:02:24 +0200, Adam Cig=E1nek <adam.ciganek gmail.co=

 wrote:

 Hello,

 Is there a function in the standard library to delete an element from
 an array (or range)? Something like:

 =A0auto a =3D [1, 2, 3, 4, 5, 6];
 =A0auto b =3D delete(a, 4);

 =A0assert([1, 2, 3, 4, 6] =3D=3D b);

 I've noticed there is eliminate in std.algorithm, which seems to be
 doing just that, but it's commented out.

 It's not difficult to roll my own, (with the help of indexOf and
 remove), but I thought that this is pretty common operation so it
 should be in the standard library.

std.algorithm has remove, which does what you want. -- Simen

Oct 24 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 24 October 2010 04:24:07 Adam Cig=E1nek wrote:
 remove removes element at a given offset. I want to remove element
 with a given value. This is example shows it better:
=20
   auto a =3D ["foo", "bar", "baz"];
   auto b =3D delete(a, "bar");
=20
   assert(["foo", "baz"] =3D=3D b);
=20
=20
 adam.
=20
 2010/10/24 Simen kjaeraas <simen.kjaras gmail.com>:
 On Sun, 24 Oct 2010 13:02:24 +0200, Adam Cig=E1nek <adam.ciganek gmail.=


=20
 wrote:
 Hello,
=20
 Is there a function in the standard library to delete an element from
 an array (or range)? Something like:
=20
  auto a =3D [1, 2, 3, 4, 5, 6];
  auto b =3D delete(a, 4);
=20
  assert([1, 2, 3, 4, 6] =3D=3D b);
=20
 I've noticed there is eliminate in std.algorithm, which seems to be
 doing just that, but it's commented out.
=20
 It's not difficult to roll my own, (with the help of indexOf and
 remove), but I thought that this is pretty common operation so it
 should be in the standard library.

std.algorithm has remove, which does what you want. =20 -- Simen


Well, then use indexOf() to get the offset and remove() to remove the eleme= nt. =2D Jonathan M Davis
Oct 24 2010
prev sibling next sibling parent =?ISO-8859-1?Q?Adam_Cig=E1nek?= <adam.ciganek gmail.com> writes:
 Well, then use indexOf() to get the offset and remove() to remove the element.

Yes, that's what I'm doing. I just thought that I maybe overlook such function in the standard library. So there is none. No problem, I'll keep using my own. Still think it would be useful to add it, because I believe such operation is quite common. thanks, adam.
Oct 24 2010
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On Sun, 24 Oct 2010 09:31:12 -0400
bearophile <bearophileHUGS lycos.com> wrote:

 Jonathan M Davis:
=20
 Well, then use indexOf() to get the offset and remove() to remove the e=


=20
 But you must test the result value of indexOf, because it returns -1 (a s=

s on 64 bit systems) when the item is missing. This is why Python has both = a way to remove an item by index and by value.
=20
 Bye,
 bearophile

In my opinion, such non-obvious complications are good reasons to have seem= ingly trivial operations implemented as builtin routines. (and should throw= error in case of failure) Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Oct 24 2010
prev sibling next sibling parent =?ISO-8859-1?Q?Adam_Cig=E1nek?= <adam.ciganek gmail.com> writes:
 In my opinion, such non-obvious complications are good reasons to have se=

ow error in case of failure) Or have them in the standard library - better for keeping the language smal= l. adam.
 Denis
 -- -- -- -- -- -- --
 vit esse estrany =E2=98=A3

 spir.wikidot.com

Oct 24 2010
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On Sun, 24 Oct 2010 15:51:29 +0200
Adam Cig=C3=A1nek <adam.ciganek gmail.com> wrote:

 In my opinion, such non-obvious complications are good reasons to have =


hrow error in case of failure)
=20
 Or have them in the standard library - better for keeping the language sm=

=20
 adam.

Yes, that's what I meant, in fact (but was unclear). Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Oct 24 2010
prev sibling next sibling parent reply "Manfred_Nowak" <svv1999 hotmail.com> writes:
Adam Cigánek wrote:

 Is there a function in the standard library to delete an element from
 an array (or range)?

arrays are computational not well suited for deleting elements, nor are lists. -manfred
Oct 24 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Manfred_Nowak:

 arrays are computational not well suited for deleting elements, nor are 
 lists.

On the other hand dynamic arrays are handy for many other purposes. So if you have just 20 items, like some buttons of your GUI, you may want to use a dynamic array to add and remove them, especially if you have handy standard functions/methods to add and remove items. The runtime, even in Python, will never show you any slowdown. Python lists are arrays dynamic to the right, similar to D dynamic arrays, and they are handy. So computational complexity considerations aren't the only things to keep in account when you write code. Bye, bearophile
Oct 24 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
spir:

 Bearophile, what do you mean with "arrays dynamic to the right"? (that they
extend/compress (only) on the right side?)

In Python you may add items at the start too of a list, but that's not an efficient operation, Python lists are amortized efficient only if you append items to their right side, because they may keep some free space only on their right site. In Python the deque collection supports efficient add/remove from both ends. Bye, bearophile
Oct 24 2010
prev sibling parent "Manfred_Nowak" <svv1999 hotmail.com> writes:
bearophile wrote:

 some buttons of your GUI

I doubt that one wants to _delete_ buttons of a GUI instead of inactivating them and the OP did ask for "a function in the standard library to delete an element from an array", i.e. arrays without any restrictions on the number of elements as supposed by you. -manfred
Oct 24 2010
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On Sun, 24 Oct 2010 14:47:43 -0400
bearophile <bearophileHUGS lycos.com> wrote:

 Manfred_Nowak:
=20
 arrays are computational not well suited for deleting elements, nor are=


 lists.


Sequences of all kinds are the worst possible kind of collection for this o= peration (not only linear search, but shift all elements placed after the o= ne found & removed). But...
 On the other hand dynamic arrays are handy for many other purposes. So if=

a dynamic array to add and remove them, especially if you have handy stand= ard functions/methods to add and remove items. The runtime, even in Python,= will never show you any slowdown. Python lists are arrays dynamic to the r= ight, similar to D dynamic arrays, and they are handy.
=20
 So computational complexity considerations aren't the only things to keep=

... Agreed. Typically, remove and such costly ops happen once in a while, w= hen indexing, traversal, slicing for which sequences are handy and super-ef= ficient happen all the time. Bearophile, what do you mean with "arrays dynamic to the right"? (that they= extend/compress (only) on the right side?)
 Bye,
 bearophile

Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Oct 24 2010
prev sibling next sibling parent =?ISO-8859-1?Q?Adam_Cig=E1nek?= <adam.ciganek gmail.com> writes:
 Your new example doesn't show it better, it's the only one you've given t=

 shows it at all. =A0What you had originally was

 =A0auto a =3D [1, 2, 3, 4, 5, 6];
 =A0auto b =3D delete(a, 4);

 =A0assert([1, 2, 3, 4, 6] =3D=3D b);

 which shows the removal of the element at index 4, not the element with
 value 4.

Yep, I made a typo. The last line was supposed to be assert([1,2,3,5,6] =3D=3D b). My bad.
 But there are further questions to be answered:

 - What do you want it to do if the value isn't in the array? =A0Just retu=

 the original array, return a copy of the original array, or throw an
 exception?

Good question. I would return the array unchanged (or maybe returning range pointing to the same data as the original array). The justification is that since I'm going to delete the element anyway, I probably "don't care" about it, so it does not matter if it's in the array in the first place. Throwing an exception does not seem useful to me.
 - What do you want it to do if the value is in the array more than once?
 =A0Remove the first, remove the last, remove all of them, or pick one at
 random?

Another good question. In the end, there should probably be more functions: deleteFirst, deleteLast, deleteAll or even deleteRandom. adam.
 Stewart.

Oct 24 2010
prev sibling parent Michael Rynn <michaelrynn optusnet.com.au> writes:
On Sun, 24 Oct 2010 13:02:24 +0200, Adam Cigánek wrote:

 Hello,
 
 Is there a function in the standard library to delete an element from an
 array (or range)? Something like:
 
   auto a = [1, 2, 3, 4, 5, 6];
   auto b = delete(a, 4);
 
   assert([1, 2, 3, 4, 6] == b);
 
 I've noticed there is eliminate in std.algorithm, which seems to be
 doing just that, but it's commented out.
 
 It's not difficult to roll my own, (with the help of indexOf and
 remove), but I thought that this is pretty common operation so it should
 be in the standard library.
 
 

void replace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff); and a delete can be done by passing null as stuff. This multipurpose template will replace with whatever gets passed as stuff, including null. import std.array; ... auto a = [1, 2, 3, 4, 5, 6]; replace(a, 4, 5, null); // delete slice 4..5 assert([1, 2, 3, 4, 6] == a); The documentation also shows comments for code that has been commented out. eg Erases element from array at index from. (code is commented out). Shows a need for doc comments to be commented out with the code they refer to, as this confused me for a bit, until I found that the 4 argument version is the only working one.
Oct 26 2010