Specify variable type for range of associative arrays.
Nicholas Wilson via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Aug 9 05:54:37 PDT 2015
On Sunday, 9 August 2015 at 01:29:16 UTC, Christopher Davies
wrote:
> I'm just learning D. Something I often do in C# is have an
> IEnumerable (Range) of some type that is then conditionally
> filtered. It looks like this:
>
> IEnumerable<Dictionary<string, string>> foo = bar;
>
> if (baz)
> {
> foo = foo.Where(d => d["key"] == value);
> }
>
> I'm trying to do the same in D. Here's what I want to do:
>
> Range!(string[string]) records =
> csvReader!(string[string])(input, null);
>
> if (where != "")
> {
> records = filter!(r => r[where] == val)(records);
> }
using UFCS (universal function call syntax) you would normally
write that as:
records =records.filter!(r => r[where] == val)();
and then leveraging D's optional parentheses as:
records =records.filter!(r => r[where] == val)
This allows you to chain them along with map, filter, reduce etc.
with ease
e.g.
auto result = someRange.filter!(e =>e.isFooCompatible).map!(e
=> foo(e)).map!(e => e.toBar).array;
do you care about the type of result? Not really. It's a range.
meaning you can pass iterate over it, pass it to other algorithms.
>
> But Range!(string[string]) isn't right, even though that's what
> the csvReader and filter statements produce. How do I declare
> that type?
>
Type inference is your friend.
auto foo = bar;
will work for any type that does not disallow copying (@disable
this(this); )
To answer your question what you probably want is not
auto records = csvReader!(string[string])(input, null);
if (where != "")
{
records = records.filter!(r => r[where] == val);
}
but:
auto records = csvReader!(string[string])(input, null);
if (where != "")
{
auto filteredRecords = records.filter!(r => r[where]
== val);
//do something with filteredRecords ...
}
or just
if (where != "")
{
// if you need the result exclude comment below
// or if your operation is for side effects only
// leave it.
/*auto result =*/ csvReader!(string[string])(input,
null)
.filter(e => somePred(e))
.continueChainingRanges(withSomeArgs)
.untilYoureDone;
}
If you just want a copy of the filtered results
if (where != "")
{
auto result = csvReader!(string[string])(input, null)
.filter(e => e[where] ==
val).array;
// .array causes a separate copy of the values of
the result of csvReader
}
Nic
More information about the Digitalmars-d-learn
mailing list