digitalmars.D.learn - Removal from std.container.Array.
- Ty Overby (18/18) Feb 10 2014 So I'm using a std.container.Array for storing systems in my
- Steven Schveighoffer (10/28) Feb 10 2014 equalRange is only valid for sorted containers or at least containers
- Steven Schveighoffer (4/6) Feb 10 2014 Sorry, I think it's remove (the STL function).
- Jakob Ovrum (43/45) Feb 10 2014 I think the correct solution is:
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
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
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
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