Open atifaziz opened 4 years ago
In your proposition, the projected value type is limited to bool
.
I propose a more generalized Map
method :
public static IEnumerable<(TSource element, TResult projection)> Map<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> func);
I reversed the order of the element in the tuple since this order is more logical for me.
Implementation is straightforward.
The two line below are equivalent:
source.Map(func);
source.Select(v=>(v, func(v));
In your proposition, the projected value type is limited to
bool
.
But that's the whole idea! Map
or Select
already exists.
Actually Map
doesn't exist in MoreLinq or I can't find it.
I neither can't find a method that do what I propose for Map.
It's generic and work with your example:
var strs = new[] { "foo", "bar", "baz" };
foreach (var (s, matched) in strs.Map(s => Regex.IsMatch(s, @"^b")))
Console.WriteLine($"{s} => {matched}");
It's replace .Select(v => (v, ...))
by .Map(v => ...)
.
every penny counts
Your foreach
example is fine but it's one example where it looks good. However, the deconstruction into s
and matched
doesn't work (yet) with neither lambdas (when using method chaining) nor from
binding in LINQ query syntax. The closest you can come to is this:
var outputs =
from (string Input, bool Matched) e in strs.Map(s => Regex.IsMatch(s, @"^b"))
select $"{e.Input} => {e.Matched}";
foreach (var output in outputs)
Console.WriteLine(output);
That's a Cast
in disguise, and even worse, doesn't work without explicit types so throws anonymous types out of the window. You might as well just use a normal projection:
var outputs =
from e in strs.Select(s => (Input: s, Matched: Regex.IsMatch(s, @"^b")))
select $"{e.Input} => {e.Matched}";
I am completely happy with closing this as too trivial and I was hoping to be challenged to that conclusion. We reject trivial additions (especially one to two liners that don't provide much algorithmic intelligence) all the time. My idea, frankly, with Match
was to somewhat complement Choose
:
var items =
strs.Match(s => Regex.IsMatch(s, @"^b"))
.Pipe(e => Console.WriteLine($"{e.Element} => {e.Success}")) // log
.Choose(e => e);
foreach (var item in items)
Console.WriteLine(item);
This is why it's not just a generic mapping. This is just making the following Select
easier, especially with respect to tuple naming and element ordering:
var items =
strs.Select(s => (Success: Regex.IsMatch(s, @"^b"), Element: s))
.Pipe(e => Console.WriteLine($"{e.Element} => {e.Success}"))
.Choose(e => e);
Your Map
works fine too but requires Choose
to reverse the tuple elements:
var items =
strs.Map(s => Regex.IsMatch(s, @"^b"))
.Pipe(e => Console.WriteLine($"{e.Element} => {e.Result}"))
.Choose(e => (e.Result, e.Element));
every penny counts
What are the pennies we are measuring or talking about here?
every penny counts
What are the pennies we are measuring or talking about here?
Like
Where
except instead of filtering, it couples the predicate's result with the tested element of the sequence.Example
Prototype
It's very trivial so the only value proposition here is tuple construction with reasonably named tuple elements (although alternatives for
Success
would beMatched
andIsMatch
).