Can I build Tuples from IEnumerables using Linq?
Asked Answered
G

2

16

I've two IEnumerable<double>s, that I want to build an IEnumerable of Tuple<int, double, double> from. Item1 of the Tuple should be the index of the item, Item2 the value in index-th place in the first collection, and Item3 the value in index-th place in the second collection. Is this something that can be done easily in Linq?

E.g.

var first = new List<double>() { 10.0, 20.0, 30.0 };
var second = new List<double>() { 1.0, 2.0, 3.0 };
var result = TupleBuild(first, second);
// result = {(0, 10.0, 1.0), (1, 20.0, 2.0), (2, 30.0, 3.0)}

where:

IEnumerable<Tuple<int, double, double>> TupleBuild(IEnumerable<double> first, IEnumerable<double> second)
{ 
     // does some funky Linq
}

I realise I could write some longhand code for this, but I'd rather not reinvent the wheel if Linq has this covered.

Gabriello answered 29/11, 2011 at 13:42 Comment(0)
S
24

How about with the Zip operator and the Select overload that provides the index of the element:

return first.Zip(second, Tuple.Create)
            .Select((twoTuple, index)
                      => Tuple.Create(index, twoTuple.Item1, twoTuple.Item2));

By the way, you might as well then make the method generic:

IEnumerable<Tuple<int, TFirst, TSecond>> TupleBuild<TFirst, TSecond>
(IEnumerable<TFirst> first, IEnumerable<TSecond> second) { ... }
Seamstress answered 29/11, 2011 at 13:45 Comment(2)
Excellent, thanks! Wish I could give you an extra up vote for introducing me to the Zip extension :)Gabriello
And I wish I could upvote twice for Zip and the overloaded Select.Xena
P
1

A more modern version updated per C# 7.0 (based on the answer of @Ani).

This uses the more readable (IMO) tuple syntax without Tuple.Create. Also note the return type and the tuple deconstruction within the Select method.

IEnumerable<(int, double, double)> TupleBuild
    (IEnumerable<double> first, IEnumerable<double> second)
    {
        return first
            .Zip(second)
            .Select((tuple, index) =>
            {
                var (fst, snd) = tuple;
                return (index, fst, snd);
            });
    }

Pianism answered 28/12, 2020 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.