簡體   English   中英

鋸齒狀到多維數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM