Consider the following structure:
IEnumerable<IEnumerable<int>> collection = new[] {
new [] {1, 2, 3},
new [] {4, 5, 6},
new [] {7, 8, 9}
};
How can I enumerate this collection so that I obtain IEnumerable<int>
collections made up of the first items, second items, etc.?
That is, {1, 4, 7}, {2, 5, 8}, ...
(Though the implementation I've chosen is int[]
objects, assume you only have IEnumerable<int>
functionality. Thanks.)
Here's an approach that uses a generator instead of recursion. There's less array construction too, so it might be faster, but that's totally conjecture.
public static IEnumerable<IEnumerable<T>> Transpose<T>(
this IEnumerable<IEnumerable<T>> @this)
{
var enumerators = @this.Select(t => t.GetEnumerator())
.Where(e => e.MoveNext());
while (enumerators.Any()) {
yield return enumerators.Select(e => e.Current);
enumerators = enumerators.Where(e => e.MoveNext());
}
}
Just my 2 cents In pure linq:
var transpond = collection.First().Select((frow,i)=>collection.Select(row=>row.ElementAt(i)));
Or with some inpurity:
var r1 = collection.First().Select((frow, i) => collection.Select(row => row.ToArray()[i]));
Code credit goes here (untested but looks fine).
public static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> values)
{
if (!values.Any())
return values;
if (!values.First().Any())
return Transpose(values.Skip(1));
var x = values.First().First();
var xs = values.First().Skip(1);
var xss = values.Skip(1);
return
new[] {new[] {x}
.Concat(xss.Select(ht => ht.First()))}
.Concat(new[] { xs }
.Concat(xss.Select(ht => ht.Skip(1)))
.Transpose());
}
}
//Input: transpose [[1,2,3],[4,5,6],[7,8,9]] //Output: [[1,4,7],[2,5,8],[3,6,9]] var result = new[] {new[] {1, 2, 3}, new[] {4, 5, 6}, new[] {7, 8, 9}}.Transpose();
Assuming all the sequences are of the same length.
static void Main(string[] args)
{
IEnumerable<IEnumerable<int>> collection =
new[]
{
new [] {1, 2, 3},
new [] {4, 5, 6 },
new [] {7, 8, 9}
};
Console.WriteLine("\tInitial");
Print(collection);
var transposed =
Enumerable.Range(0, collection.First().Count())
.Select(i => collection.Select(j => j.ElementAt(i)));
Console.WriteLine("\tTransposed");
Print(transposed);
}
static void Print<T>(IEnumerable<IEnumerable<T>> collection)=>
Console.WriteLine(string.Join(Environment.NewLine, collection.Select(i => string.Join(" ", i))));
Gives:
Initial
1 2 3
4 5 6
7 8 9
Transposed
1 4 7
2 5 8
3 6 9
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With