How to implement filterMap

Christian Köstlin christian.koestlin at gmail.com
Fri Dec 29 23:10:47 UTC 2023


Is there a way to implement filterMap (meaning do mapping of a 
range, but if something happens during the map, leave this 
element out of the resulting range).
I have two solutions (one is with evaluating the mapping function 
several times), and one tries to store the result for the next 
front call like this.
Both do not seem very clean for all possible types. Here the 
version that tries to cache the mapping results.

```d
template filterMap(mapping...) if (mapping.length == 1)
{
     auto filterMap(Range)(Range range)
     {
         import std.range : ElementType, empty;
         import std.functional : unaryFun;

         alias RangeElement = ElementType!Range;
         alias mappingFunction = unaryFun!mapping;
         typeof(mappingFunction(RangeElement.init)) result;

         void findNext() {
             while (!range.empty)
             {
                 try
                 {
                     result = mappingFunction(range.front);
                     break;
                 }
                 catch (Exception e)
                 {
                     range.popFront;
                 }
             }
         }
         findNext();
         struct FilterMap
         {
             bool empty()
             {
                 return range.empty;
             }

             auto ref front()
             {
                 return result;
             }

             void popFront()
             {
                 range.popFront;
                 findNext();
             }
         }

         return FilterMap();
     }
}

@("filterMap") unittest {
     import std.conv : to;
     import std.array : array;
     ["1", "2", "abc", ""].filterMap!(s => s.to!int * 
2).array.should == [2, 4];
}
```

Kind regards,
Christian



More information about the Digitalmars-d-learn mailing list