Using filter with std.container.Array.

Soulsbane via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Mar 22 19:53:40 PDT 2017


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.



More information about the Digitalmars-d-learn mailing list