On Wednesday, 22 March 2017 at 07:30:48 UTC, Jonathan M Davis wrote:
On Wednesday, March 22, 2017 07:06:47 Soulsbane via Digitalmars-d-learn wrote:
Example code:
struct Foo
{
   string name;
   size_t id;
}

Array!Foo foo_;

I get errors when I try to use filter like this:

auto found = filter!((Foo data, size_t id) => data.id ==
id)(foo_[], 100);

I get this error
source/app.d(15,62): Error: template
std.algorithm.iteration.filter!(function (Foo data, ulong id) => data.id == id).filter cannot deduce function from argument types
!()(RangeT!(Array!(Foo)), int), candidates are:
/usr/include/dmd/phobos/std/algorithm/iteration.d(1089,10):
std.algorithm.iteration.filter!(function (Foo data, ulong id) =>
data.id == id).filter(Range)(Range range) if
(isInputRange!(Unqual!Range))

I can't figure out what I'm doing wrong. Thanks!

filter takes a unary predicate that gets called on each element in a range. It's not going to work with a function that takes two arguments, and filter itself isn't going to take two arguments. You could do something like

auto result = filter!(a => a.id == 100)(foo_[]);

but you can't pass multiple arguments to filter. Also, if you're looking to find an element, then find would make more sense than filter, since filter is going to give you a lazy range with every element that matches the predicate, whereas find is just going to iterate the range until it finds the element (or is empty) and then returns the range. But I don't know whether calling the variable found was just the name you came up with or whether you're really trying to do a find operation rather than filter.

- Jonathan M Davis

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.

Reply via email to