www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Removal from std.container.Array.

reply "Ty Overby" <ty pre-alpha.com> writes:
So I'm using a std.container.Array for storing systems in my 
program, and I need to search through the array to find the 
system that I want to remove and then shift from that.

In Java I'd write

     ArrayList<System> systems;
     ....
     systems.remove(system);

And in D I was hoping to write

     Array!System systems;
     ....
     systems.linearRemove(systems.equalRange(system));

But for some reason equalRange isn't defined on 
std.container.Array, nor is it a module function.

I also tried

     systems.linearRemove(systems[].filter!(a => a == system));

but FilterResult isn't the same type as Array.Range.


I have to be missing something really basic.  It couldn't 
possibly be this hard to remove an element from an array.
Feb 10 2014
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 10 Feb 2014 16:47:34 -0500, Ty Overby <ty pre-alpha.com> wrote:

 So I'm using a std.container.Array for storing systems in my program,  
 and I need to search through the array to find the system that I want to  
 remove and then shift from that.

 In Java I'd write

      ArrayList<System> systems;
      ....
      systems.remove(system);

 And in D I was hoping to write

      Array!System systems;
      ....
      systems.linearRemove(systems.equalRange(system));

 But for some reason equalRange isn't defined on std.container.Array, nor  
 is it a module function.
equalRange is only valid for sorted containers or at least containers where the complexity to iterate over the range is sublinear. An array search would be linear.
 I also tried

      systems.linearRemove(systems[].filter!(a => a == system));

 but FilterResult isn't the same type as Array.Range.


 I have to be missing something really basic.  It couldn't possibly be  
 this hard to remove an element from an array.
Typically in STL, you use partition and then delete the partitioned elements. I would look for something like that, maybe someone with more experience with std.algorithm can chime in. -Steve
Feb 10 2014
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 10 Feb 2014 16:54:58 -0500, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 Typically in STL, you use partition and then delete the partitioned  
 elements.
Sorry, I think it's remove (the STL function). -Steve
Feb 10 2014
prev sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 10 February 2014 at 21:47:35 UTC, Ty Overby wrote:
 I have to be missing something really basic.  It couldn't 
 possibly be this hard to remove an element from an array.
I think the correct solution is: systems.linearRemove(systems[].find(system)[0 .. 1]); Usually containers have an overload of *[Rr]emove that takes `Take!Range`, allowing: systems.linearRemove(systems[].find(system).takeOne()); std.container.Array not having overloads for `Take!Range` looks like an oversight. To the uninitiated this can look ridiculous, but hear me out first. First of all, the unary slice operation (the empty brackets: []) is the container primitive to get a range spanning the entire container. It is arguably the most fundamental container primitive, and is crucial when using other container primitives, as they often take range parameters. IMO, it would be a nice compiler enhancement to raise a tailored error message in cases where [] is forgotten (probably non-trivial to implement, though). With that out of the way: in D, both ranges and containers follow the principle that primitives are subject to restrictions on algorithmic complexity to avoid the quadratic complexity minefield that the Java approach heralds through deceptive abstraction of linear algorithms (of which ArrayList/List/Collection.remove is a good example). Therefore, a primitive equivalent of Java's List/Collection.remove is not welcome in D. Often when linear search is required for this kind of operation, the user has chosen the wrong data structure, so the absence of deceptive abstractions from the core API is *usually* a non-issue. Of course, sometimes linear search is perfectly justified, especially when it comes to (smallish) arrays, or code that is only run very rarely. In these cases, the equivalent D code using range algorithms (shown above) has advantages; we can glean two important artefacts: a) linear search is at play (because of `find`), and b) only the first element found is removed. The obvious disadvantage is that writing such code in the first place requires a relatively high degree of familiarity with Phobos containers and ranges. That said, it's probably offset by the fact that when you *do* start picking up Phobos' generic algorithms and primitives, you can apply them everywhere - learning the API of a new container is just a matter of glancing over what primitives it supports. Better documentation - such as adding examples - is definitely in order to ease this learning, though.
Feb 10 2014