std.container & ranges

Steven Schveighoffer schveiguy at yahoo.com
Mon Oct 31 07:38:47 PDT 2011


On Mon, 31 Oct 2011 05:16:11 -0400, Dmitry Olshansky  
<dmitry.olsh at gmail.com> wrote:

> On 31.10.2011 11:16, Tobias Pankrath wrote:
>> Jonathan M Davis wrote:
>>
>>>   find allows
>>> you to do that just fine, and such a remove function would simply be
>>> duplicating its functionality.
>>
>> But this thread serves as a proof that it is not obvious and something  
>> like
>> containers should be obvious to use. Deleting an element with a certain
>> value is a common task and should should not take
>> three function calls, with functions from three different modules.
>>
>>> You would be doing exactly the same thing in C++ except that it would  
>>> be
>>> with an iterator rather than a range. You would use find to find the
>>> iterator to the element that you wanted and then you'd pass that to the
>>> list's erase function.
>> I don't think we should refer to C++ as an benchmark for ease of use.
>>
>> How do you delete every occurence of v? Not just the first one? Is this
>> equally "easy" with find and take? I didn't find an easy way not
>> envolving a loop within 10 Minutes by reading the documentation.
>
> It is, let's use remove from std.algorithm! ... though there is no  
> overload of remove for forward ranges ... crap, worthy of bugzilla  
> report. Or SList could be special enough to offer a built-in remove with  
> predicate done in O(n).
>
> However this should work( yet because of apparent bug in SList it  
> doesn't). The bug is:
> Line 1294 of std.container should be:
> 	 for (; !r.empty; r.popFront())
> ...
> or it will remove the whole container.
>
> Code:
> import std.container, std.range;
> import std.functional, std.algorithm, std.stdio;
>
> void removeFromList(alias pred, T)(ref SList!T s)
> {
> 	static if(is(typeof(pred) == string))
> 		alias unaryFun!pred Pred;
> 	else
> 		alias pred Pred;
> 	for(auto r=s[]; !r.empty; )
> 	{
> 		if(Pred(r.front))
> 		{
> 			r = s.linearRemove(take(r,1));
> 			continue;
> 		}
> 		else
> 			r.popFront();
> 	}
> }
>
> void main()
> {
> 	SList!int list(20, 30, 40, 50, 60); // will work with stock Phobos if  
> the first element % 20 != 0
> 	removeFromList!"a % 20 == 0"(list);
> 	writeln(list[]);
> 	
> }
>
> And more importantly, it still would be horribly slow O(N^2).  
> Personally, because of that I'd prefer hand-rolled intrusive  
> singly-linked list any time of day.

ahem, using dcollections:

foreach(ref doRemove, cell; &organism.purge)
     doRemove = cell.x == x && cell.y == y;

complexity: O(n)

:)

-Steve


More information about the Digitalmars-d-learn mailing list