Using filter with std.container.Array.

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Mar 22 20:02:54 PDT 2017


On Thursday, March 23, 2017 02:53:40 Soulsbane via Digitalmars-d-learn 
wrote:
> Thanks for the reply Jonathan! Yes, I was trying to find all the
> ids that match but couldn't get find to work. So I think I have
> missed something somewhere.
>
> As a quick example:
> import std.stdio;
> import std.algorithm;
> import std.container;
>
> struct Foo
> {
>    string name;
>    size_t id;
> }
>
> Array!Foo foo_;
>
> void main(string[] arguments)
> {
>   Foo first;
>   first.id = 200;
>
>   Foo second;
>   second.id = 100;
>
>   Foo third;
>   third.id = 345;
>
>   Foo fourth;
>   fourth.id = 100;
>
>   foo_.insert(first);
>   foo_.insert(second);
>   foo_.insert(third);
>   foo_.insert(fourth);
>
>   auto filterIt = filter!((Foo data) => data.id == 100)(foo_[]);
>   auto foundIt = find!((Foo data) => data.id == 100)(foo_[]);
>   writeln(filterIt);
>   writeln(foundIt);
> }
>
> Will print:
> [Foo("", 100), Foo("", 100)]
> [Foo("", 100), Foo("", 345), Foo("", 100)]
>
> I only want the ids that match 100. Looking at find's
> documentation it looks like it's returning exactly as it should
> but not the way I want. No 345 id.
>
> Thanks for the help. I have this code working just fine using
> foreach and have been trying to learn this different way of doing
> things lately and my brain hurts :). Thanks again.

find just iterates to the first element that matches. It doesn't affect the
range beyond that. It works basically the same way that find would work with
iterators in that it iterates until it finds the element you're looking for.
However, since ranges then refer to more than one element at a time, the
rest of the range beyond that element is still there.

filter, on the other hand, creates a lazy range which skips the elements in
the original range which do not match the predicate. It doesn't actually do
anything until you iterate over it.

So, if you're looking specifically for _all_ of the elements in a range
which match a predicate and no other elements from that range (as it sounds
like you're doing), then filter is the correct choice. If, on the other
hand, you just want to find the first element that matches and then do
who-knows-what with the rest of the range, then find would be appropriate.

Note that because filter is lazy, it results in a new range which wraps the
original, whereas find returns the original range with elements popped off.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list