[英]How do you transpose dimensions in a 2D collection using LINQ?
考慮以下結構:
IEnumerable<IEnumerable<int>> collection = new[] {
new [] {1, 2, 3},
new [] {4, 5, 6},
new [] {7, 8, 9}
};
如何枚舉此集合以便獲取由第一項,第二項等組成的IEnumerable<int>
集合?
也就是說,{1,4,7},{2,5,8},......
(雖然我選擇的實現是int[]
對象,但假設你只有IEnumerable<int>
功能。謝謝。)
這是一種使用生成器而不是遞歸的方法。 陣列構造也較少,因此可能更快,但這完全是猜想。
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());
}
}
代碼信用在這里 (未經測試,但看起來很好)。
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();
只需我的2美分In pure linq:
var transpond = collection.First().Select((frow,i)=>collection.Select(row=>row.ElementAt(i)));
或者有一些不成熟:
var r1 = collection.First().Select((frow, i) => collection.Select(row => row.ToArray()[i]));
如果保證所有元素的長度相同,則可以執行以下操作:
IEnumerable<IEnumerable<int>> Transpose(IEnumerable<IEnumerable<int>> collection)
{
var width = collection.First().Count();
var flattened = collection.SelectMany(c => c).ToArray();
var height = flattened.Length / width;
var result = new int[width][];
for (int i = 0; i < width; i++)
{
result[i] = new int[height];
for (int j = i, k = 0; j < flattened.Length; j += width, k++)
result[i][k] = flattened[j];
}
return result;
}
假設所有序列長度相同。
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))));
得到:
Initial
1 2 3
4 5 6
7 8 9
Transposed
1 4 7
2 5 8
3 6 9
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.