在C#中展开一个数组

16

C#中最短的代码是什么可以将一个数组压平?

例如,我想要:

[[1,2],[2,3],[4,5]]

添加到数组中

[1,2,3,4,5]

我正在寻找完成此事的最短路径。


2
https://dev59.com/q2025IYBdhLWcg3w6aYX - Marko
1
https://dev59.com/u3I-5IYBdhLWcg3w99kH - Nathan Bierema
@Marko 有没有更简洁的方法? - Naman
@Naman 这就是最简短的了。 - Nathan Bierema
1
它是二维数组还是交错数组?如果它是二维(或多维)数组,那么它已经被展平了。 - Hari Prasad
显示剩余4条评论
2个回答

39

也许我对“最短代码”的理解方式有误,但我建议使用LINQ SelectManyDistinct

var values = new[]
{
    new[] { 1, 2 },
    new[] { 2, 3 },
    new[] { 4, 5 },
};

var flattenedUniqueValues = values.SelectMany(x => x).Distinct();

6
将一个交错数组转换为一维数组很简单,可以在 O(n) 的时间内完成,需要 n 的空间(其中 n 是第二维数组长度的总和)。然而,在您的示例中,似乎要删除重复值-这不是扁平化数组,但仍然可以在 O(n) 时间内完成,但需要 O(2n) 的空间,因为您需要一个哈希表进行 O(1) 的重复值查找。
预先知道最终数组中将存在多少元素可能存在问题。一个简单的解决方案是将其附加到 List<T> 并在末尾调用 .ToArray(),但这将导致 O(2n) 的时间和 O(3n) 的空间(但由于 List<T> 内部重新分配,潜在地更多)。
Int32[][] jagged = ...
HashSet<Int32> seen = new HashSet<Int32>();
List<Int32> ret = new List<Int32>();

for(int i = 0; i < jagged.Length; i++) {
    for(int j = 0; j < jagged[i].Length; j++) {
        Int32 val = jagged[i][j];
        if( !seen.Contains( val ) ) {
            ret.Add( val );
            seen.Add( val );
        }
    }
}

return ret.ToArray(); // This takes O(n) time and will allocate O(n) additional space.

另一种解决方案是自己进行两次遍历:第一次确定输出的大小,然后第二次遍历生成输出 - 这将导致更少的复制:时间复杂度为 O(2n),空间复杂度也为 O(2n)

Int32[][] jagged = ...
HashSet<Int32> seen = new HashSet<Int32>();

// Pass 1
for(int i = 0; i < jagged.Length; i++) {
    for(int j = 0; j < jagged[i].Length; j++) {
        Int32 val = jagged[i][j];
        seen.Add( val ); // HashSet.Add is safe/idempotent
    }
}

Int32[] ret = new Int32[ seen.Count ];

// Pass 2
seen.Clear();

Int32 retIdx = 0;
for(int i = 0; i < jagged.Length; i++) {
    for(int j = 0; j < jagged[i].Length; j++) {
        Int32 val = jagged[i][j];
        if( !seen.Contains( val ) ) {
            ret[++retIdx] = val;
            seen.Add( val );
        }
    }
}

return ret;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接