www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.algorithm.remove from array of custom classes?

reply Tim K. <no nope.com> writes:
Hi!

I'm trying to remove an item from an array of objects. But I get 
error messages when compiling (see below) which I do not 
understand. I figured I had to override opEquals for it to work, 
but no.
How do I get this to work?

Regards



     class A
     {
         this(string si, uint ui) { s = si; u = ui; }
         string s;
         uint u;

         override bool opEquals(Object obj)
         {
             A o = cast(A)obj;
             return (s == o.s) && (u == o.u);
         }
     }

     int main(string[] argv)
     {
         import std.stdio: writeln;
         import std.algorithm: remove;
         A a = new A("a", 1);
         A b = new A("b", 2);
         A[] as = [a, b];
         as.remove(a);
         writeln(as);

         return 0;
     }


Error:

/usr/include/dmd/phobos/std/algorithm/mutation.d(1503): Error: 
template std.range.primitives.popFrontExactly cannot deduce 
function from argument types !()(A[], A), candidates are:
/usr/include/dmd/phobos/std/range/primitives.d(1791):        
std.range.primitives.popFrontExactly(Range)(ref Range r, size_t 
n) if (isInputRange!Range)
/usr/include/dmd/phobos/std/algorithm/mutation.d(1504): Error: 
template std.range.primitives.popFrontExactly cannot deduce 
function from argument types !()(A[], A), candidates are:
/usr/include/dmd/phobos/std/range/primitives.d(1791):        
std.range.primitives.popFrontExactly(Range)(ref Range r, size_t 
n) if (isInputRange!Range)
/usr/include/dmd/phobos/std/algorithm/mutation.d(1505): Error: 
cannot implicitly convert expression (from) of type dummy.A to 
ulong
dummy.d(21): Error: template instance 
std.algorithm.mutation.remove!(cast(SwapStrategy)2, A[], A) error 
instantiating
Dec 09 2015
parent reply BBaz <b2.temp gmx.com> writes:
On Wednesday, 9 December 2015 at 13:05:31 UTC, Tim K. wrote:
 Hi!

 I'm trying to remove an item from an array of objects. But I 
 get error messages when compiling (see below) which I do not 
 understand. I figured I had to override opEquals for it to 
 work, but no.
 How do I get this to work?
You should read the documentation, there is two errors: 1) remove works with an index 2) remove does not remove in place so with ~~~~~~~~~~~~~~~~~~~~~~~~~~ import std.stdio; import std.algorithm; class A { this(string si, uint ui) { s = si; u = ui; } string s; uint u; override bool opEquals(Object obj) const { if (A o = cast(A)obj) return (s == o.s) && (u == o.u); else return false; } } void main(string[] argv) { A a = new A("a", 1); A b = new A("b", 2); A[] as = [a, b]; as = as.remove(0); writeln(as); } ~~~~~~~~~~~~~~~~~~~~~~~~~~ also, off topic but 2 other advices/errors 3) opEquals can be 'const' because the method doesn't mutate the state of the object 4) your cast wasn't safe
Dec 09 2015
next sibling parent reply Tim K. <no nope.com> writes:
On Wednesday, 9 December 2015 at 13:13:36 UTC, BBaz wrote:

 1) remove works with an index
I guess I did read it wrong. Sorry. Is there a convenience function that allows me to remove an/all object(s) with a certain value from an array or do I need to write one myself?
 2) remove does not remove in place
That's fine.
Dec 09 2015
next sibling parent Andrea Fontana <nospam example.com> writes:
On Wednesday, 9 December 2015 at 13:23:00 UTC, Tim K. wrote:
 On Wednesday, 9 December 2015 at 13:13:36 UTC, BBaz wrote:

 1) remove works with an index
I guess I did read it wrong. Sorry. Is there a convenience function that allows me to remove an/all object(s) with a certain value from an array or do I need to write one myself?
 2) remove does not remove in place
That's fine.
void main(string[] argv) { A a = new A("a", 1); A b = new A("b", 2); A[] as = [a, b]; as = as.remove!(x => x == a); writeln(as); } If array is sorted you can find the index of that element and then remove it by index.
Dec 09 2015
prev sibling parent cym13 <cpicard openmailbox.org> writes:
On Wednesday, 9 December 2015 at 13:23:00 UTC, Tim K. wrote:
 On Wednesday, 9 December 2015 at 13:13:36 UTC, BBaz wrote:

 Is there a convenience function that allows me to remove an/all 
 object(s) with a certain value from an array or do I need to 
 write one myself?
Here are some elements of strategy: import std.algorithm; import std.array; auto arr = [2, 3, 4, 5, 3, 2, 4]; // Remove all arr = arr.remove!(x => x==3); assert(arr == [2, 4, 5, 2, 4];); // remove all (filter works lazilly, we use array to get an array nonetheless) // filter is useful when composing functions, not so much here arr = arr.filter!(x => x==2).array; assert(arr == [4, 5, 4]); // Remove one, throw if the element is not found, // we use countUntil to get the index. arr = arr.remove(arr.countUntil(4)); assert(arr == [5, 4]); also you may be interested in reading this: http://p0nce.github.io/d-idioms/#Adding-or-removing-an-element-from-arrays
Dec 09 2015
prev sibling parent Andrea Fontana <nospam example.com> writes:
On Wednesday, 9 December 2015 at 13:13:36 UTC, BBaz wrote:
 3) opEquals can be 'const' because the method doesn't mutate 
 the state of the object
 4) your cast wasn't safe



Maybe something like this works better: ... override bool opEquals(T)(T obj) const if (is(T : A)) { return (s == o.s) && (u == o.u); } ...
Dec 09 2015