Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On 2/25/11, spir <denis.spir@gmail.com> wrote:
> * delete an element in an associative array
Just use .remove?
void main()
{
auto var = ["a" : 1];
var.remove("b"); // nothing happens
var.remove("a"); // "a" key is gone
assert(!var.length); // empty
}
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On Friday, February 25, 2011 11:30:28 spir wrote: > Hello, > > What's the idiomatic way to: > > * delete an element in an associative array If you have the key, then just use remove. The online documentation for asseciative array discusses it. e.g. b.remove("hello"); If you're looking to remove by value, however, you're going to have to figure out what its key is. And if you want to remove _all_ elements with the same value, then you're going to need to find _all_ of their keys. The best way to do that would probably just be to use a foreach loop: foreach(k, v; aa) { if(v == value) aa.remove(k); } I'm not sure if there are any problems with removing from an associative array while iterating over it though. I wouldn't think so, but I don't know so. Worst case though, you save the list of keys to remove and then remove them all once you have them all. > * delete an element in a dyn array I don't think that there is one right now. There should probably be a function in std.array which does what remove in std.container would do, but I don't believe that there's a function for it right now. So, the simplest way at the moment (albeit not the most efficient) would probably do to something like auto found = findSplit(arr, value); auto newArr = array(chain(found[0], found[2])); The efficient way to do it, however, would involve shifting all of the elements in the array, which is more complicated and not the kind of code that you really want to be rewriting every time that you need to remove an element. But you _do_ need to remember that removing an arbitrary element from an array is _not_ cheap, because even in the most efficient case, that means moving a potentially large number of elements in the array - unlike a linked list where removal is cheap. Of course, popFront and popBack would be the best way to remove from the ends of an array, and _that_ is efficient. > * insert an element in a dyn array Same as remove. There's no function for doing it at the moment. The best way at present would probably be to just concatenate the slices. auto newArr = arr[0 .. i] ~ [value] ~ [i .. $]; But again, that's not particularly efficient. What you'd really want to do would be increase the size of the array by one, shift all of the elements after the insertion point over by one, and then set the element at the insertion point to the value that you're inserting. And of course, if appending to the array, ~= would be the best way to do it. And again, inserting into arrays is _not_ efficient regardless, so if you're doing that sort of thing a lot, you probably should be using a different type of container. - Jonathan M Davis |
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Friday, February 25, 2011 11:30:28 spir wrote:
>> Hello,
>>
>> What's the idiomatic way to:
>>
>> * delete an element in an associative array
>
> If you have the key, then just use remove. The online documentation for
> asseciative array discusses it. e.g.
>
> b.remove("hello");
>
> If you're looking to remove by value, however, you're going to have to figure out
> what its key is. And if you want to remove _all_ elements with the same value,
> then you're going to need to find _all_ of their keys. The best way to do that
> would probably just be to use a foreach loop:
>
> foreach(k, v; aa)
> {
> if(v == value)
> aa.remove(k);
> }
>
> I'm not sure if there are any problems with removing from an associative array
> while iterating over it though. I wouldn't think so, but I don't know so. Worst
> case though, you save the list of keys to remove and then remove them all once
> you have them all.
It is illegal to remove from an AA you are iterating. I've learned first hand that this causes subtle memory bugs. Do not do this.
However, dcollections supports this idiom via the purge operation:
foreach(ref doPurge, v; &mymap.purge)
doPurge = (v == value);
-Steve
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On 2/25/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>
>> * insert an element in a dyn array
>
> Same as remove. There's no function for doing it at the moment.
std.array.insert:
int[] a = [ 1, 2, 3, 4 ];
a.insert(2, [ 1, 2 ]);
assert(a == [ 1, 2, 1, 2, 3, 4 ]);
afaik insert was missing from the documentation in the last release (I've reported it), but now it's back in. So maybe that's why nobody knew about it.
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday 25 February 2011 12:16:19 Steven Schveighoffer wrote:
> On Fri, 25 Feb 2011 15:09:44 -0500, Jonathan M Davis <jmdavisProg@gmx.com>
>
> wrote:
> > On Friday, February 25, 2011 11:30:28 spir wrote:
> >> Hello,
> >>
> >> What's the idiomatic way to:
> >>
> >> * delete an element in an associative array
> >
> > If you have the key, then just use remove. The online documentation for asseciative array discusses it. e.g.
> >
> > b.remove("hello");
> >
> > If you're looking to remove by value, however, you're going to have to
> > figure out
> > what its key is. And if you want to remove _all_ elements with the same
> > value,
> > then you're going to need to find _all_ of their keys. The best way to
> > do that
> > would probably just be to use a foreach loop:
> >
> > foreach(k, v; aa)
> > {
> >
> > if(v == value)
> >
> > aa.remove(k);
> >
> > }
> >
> > I'm not sure if there are any problems with removing from an associative
> > array
> > while iterating over it though. I wouldn't think so, but I don't know
> > so. Worst
> > case though, you save the list of keys to remove and then remove them
> > all once
> > you have them all.
>
> It is illegal to remove from an AA you are iterating. I've learned first hand that this causes subtle memory bugs. Do not do this.
Good to know. I was wondering. It's simple enough though to just make a list of the keys to remove and then remove them afterwords.
- Jonathan M Davis
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On Friday 25 February 2011 12:09:44 Jonathan M Davis wrote:
> On Friday, February 25, 2011 11:30:28 spir wrote:
> > * delete an element in a dyn array
>
> I don't think that there is one right now. There should probably be a function in std.array which does what remove in std.container would do, but I don't believe that there's a function for it right now. So, the simplest way at the moment (albeit not the most efficient) would probably do to something like
>
> auto found = findSplit(arr, value);
> auto newArr = array(chain(found[0], found[2]));
>
> The efficient way to do it, however, would involve shifting all of the elements in the array, which is more complicated and not the kind of code that you really want to be rewriting every time that you need to remove an element. But you _do_ need to remember that removing an arbitrary element from an array is _not_ cheap, because even in the most efficient case, that means moving a potentially large number of elements in the array - unlike a linked list where removal is cheap.
>
> Of course, popFront and popBack would be the best way to remove from the ends of an array, and _that_ is efficient.
Actually, on reflection, we probably _don't_ want a remove like std.container uses. What we probably want is something like remove and removeInPlace. The fact that dynamic arrays are really ranges rather than containers makes removing in place _far_ less desirable in many cases, and it's not necessarily a good idea to treat an array like a container in std.container.
- Jonathan M Davis
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On Friday 25 February 2011 12:30:00 Andrej Mitrovic wrote:
> On 2/25/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> >> * insert an element in a dyn array
> >
> > Same as remove. There's no function for doing it at the moment.
>
> std.array.insert:
>
> int[] a = [ 1, 2, 3, 4 ];
> a.insert(2, [ 1, 2 ]);
> assert(a == [ 1, 2, 1, 2, 3, 4 ]);
>
> afaik insert was missing from the documentation in the last release (I've reported it), but now it's back in. So maybe that's why nobody knew about it.
Ah. Good to know. Its not the sort of thing that I'm generally looking to do, however, so I don't tend to think about it. I don't believe that I've ever seen the function in the docs before, so that would explain why didn't know about it.
- Jonathan M Davis
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
I have asked for remove before, I got some responses here (in fact, Jonathan made an enhancement request for it): http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_object_from_a_range_23212.html The topic was derailed, but essentially you can provide a predicate as a function literal to do the work: import std.stdio; import std.algorithm; void main() { int[] elements = [1, 2, 3, 2, 4]; int needle = 2; elements = remove!((item) {return item == needle;} )(elements); assert(elements == [1, 3, 4]); } |
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On Friday, February 25, 2011 12:51:53 Andrej Mitrovic wrote:
> I have asked for remove before, I got some responses here (in fact, Jonathan made an enhancement request for it):
>
> http://www.digitalmars.com/d/archives/digitalmars/D/learn/Removing_an_objec t_from_a_range_23212.html
>
> The topic was derailed, but essentially you can provide a predicate as a function literal to do the work:
>
> import std.stdio;
> import std.algorithm;
>
> void main()
> {
> int[] elements = [1, 2, 3, 2, 4];
> int needle = 2;
>
> elements = remove!((item) {return item == needle;} )(elements);
> assert(elements == [1, 3, 4]);
> }
Actually, you can probably just use replace and give it an empty range for the third argument. Still, there should probably be a function in std.array which removes a value from an array based on its value. A function that's essentially identical to the version of replace which takes two ranges in addition to the array but doesn't take the range to replace with would probably do the trick:
R1 replace(R1, R2)(R1 subject, R2 toRemove) if(...) {...}
- Jonathan M Davis
|
February 25, 2011 Re: array idioms | ||||
---|---|---|---|---|
| ||||
On 02/25/2011 08:55 PM, Andrej Mitrovic wrote: > On 2/25/11, spir<denis.spir@gmail.com> wrote: >> * delete an element in an associative array > > Just use .remove? > > void main() > { > auto var = ["a" : 1]; > var.remove("b"); // nothing happens > var.remove("a"); // "a" key is gone > > assert(!var.length); // empty > } Sh*t, I have missed it. Sorry for the no*se. But where is this func implemented? I could not find it by browsing. (It's also not in object.d, apparently; while usually when I cannot find something, it's hidden in there ;-) Denis -- _________________ vita es estrany spir.wikidot.com |
Copyright © 1999-2021 by the D Language Foundation