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