[英]Jagged to Multidimensional Array
我和我的同事目前正在面臨一系列編碼挑戰。
然而,我們喜歡讓事情稍微有點讓我們的答案降下來(是的,我知道,C#不是最好的高爾夫語言)
我們最近的一個涉及旋轉立方體(int [,])。 所以最終我們想出了一個賭注,如果我可以在一行中得到它,他會給我買午餐,反之亦然。
經過許多退格和言語之后,我的母親不願意聽我說,我終於得到了它,或者我認為。
我最終得到了int [] []。
而據我所知,沒有簡單的方法將其轉換為int [,]。 所以我問這一行是否真的可行。
編輯1
我會發布我的源代碼,然后我的同事可以找到它,我可能會失去免費的午餐。
您至少需要兩行,一行用於聲明結果數組,另一行用於實際復制數據。
您可以先將數組數組展平為單個數組,然后使用Buffer.BlockCopy
將所有數據復制到結果數組中。
這是一個例子:
var source = new int[][] {
new int[4]{1,2,3,4},
new int[4]{5,6,7,8},
new int[4]{1,3,2,1},
new int[4]{5,4,3,2}
};
var expected = new int[4,4] {
{1,2,3,4},
{5,6,7,8},
{1,3,2,1},
{5,4,3,2}
};
var result = new int[4, 4];
// count = source.Length * source[0].Length * sizeof(int) = 64, since BlockCopy is byte based
// to be dynamically you could also use System.Runtime.InteropServices.Marshal.SizeOf(source[0][0]) instead of sizeof(int)
Buffer.BlockCopy(source.SelectMany(r => r).ToArray(), 0, result, 0, 64);
result.Dump("result");
expected.Dump("expected");
結果:
如果你堅持要花哨:你可以用委托動態調用BlockCopy
讓該委托返回Object
這樣你就可以用它來分配一個匿名類,這顯然符合你的規則,並將所有東西都包裝成一個集合所以你用這樣的單行怪物結束:
var result = new[]{ new int[4, 4] }.Select(x => new { r = x, tmp = Delegate.CreateDelegate(typeof(Action<Array, int, Array, int, int>), typeof(Buffer).GetMethod("BlockCopy")).DynamicInvoke(new Object[]{source.SelectMany(r => r).ToArray(), 0, x, 0, 64})}).First().r;
你應該嘗試學習javascript(我正在使用的是一個非常常見的模式庫)。
int[][] jagged = new[] { new[] { 1, 2, 3, 4, 5 }, new[] { 6, 7, 8, 9, 10 } };
int[,] array = ((Func<int[][], int[,]>)(x =>
{
int[,] temp = new int[x.Length, x.Length != 0 ? x[0].Length : 0];
for (int i = 0; i < x.Length; i++)
{
for (int j = 0; j < x[0].Length; j++)
{
temp[i, j] = x[i][j];
}
}
return temp;
}))(jagged);
int[,] array =
只能刪除行尾。 我聲明一個匿名方法然后調用它(參見(jagged)
?這是我調用匿名方法)。
單一聲明版本
int[,] array = jagged.Length == 0 ?
new int[0,0] :
jagged.SelectMany(x => x)
.Select((x, ix) => new
{
i = ix / jagged[0].Length,
y = ix % jagged[0].Length,
val = x
})
.Aggregate(new int[jagged.Length, jagged[0].Length], (md, x) => (md[x.i, x.y] = x.val) == x.val ? md : null);
這里我使用的是Aggregate()
方法。 TSeed
是目標多維數組。 注意(md[xi, xy] = x.val) == x.val ? md : null
(md[xi, xy] = x.val) == x.val ? md : null
:我需要分配md[xi, xy] = x.val
但是我需要返回md
(因為Aggregate
要求函數以這種方式工作)。 我做了一個無用的檢查(md[xi, xy] = x.val) == x.val
並使用三元運算符返回md
。
請注意,我正在關閉一個變量( jagged
),但是可以刪除閉包(我認為)......嗯嗯似乎很復雜。
如果你被允許使用Func<>
和lambda,你當然可以做一個通用的擴展來轉換你調用它的對象。
/// <typeparam name="T">Output type</typeparam>
/// <typeparam name="U">Calling type</typeparam>
/// <param name="obj">object to pipe</param>
/// <param name="func">blackbox function</param>
/// <returns>whatever</returns>
public static T ForThis<T,U> (this U obj, Func<U,T> func)
{
return func(obj);
}
有了這個,您應該能夠通過執行以下操作將int [,]轉換為int [] []:
int[][] output = input.ForThis<int[][], int[,]>((obj) =>
{
// transform obj == input of type int[,] into int[][]
throw new NotImplementedException();
});
雖然我承認這個解決方案真的像是作弊,因為你只是將多線轉換包裝成一個lambda。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.