Сгладить массив в С#

В С# какой самый короткий код для выравнивания массива?

Например, я хочу

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

в массив

[1,2,3,4,5]

Я ищу самый короткий способ сделать это.


person Naman    schedule 09.04.2016    source источник
comment
stackoverflow.com/questions/5721360/   -  person Marko    schedule 09.04.2016
comment
Хотя я сомневаюсь, что это самый эффективный способ сделать это, я бы создал функцию расширения, которая сделает это за меня. Он будет рекурсивно перебирать все элементы и элементы, содержащиеся внутри элементов, и добавлять их в список «T». Затем он вернет List.ToArray()   -  person RoyalPotato    schedule 09.04.2016
comment
stackoverflow.com/questions/1590723/flatten-list-in-linq   -  person Nathan Bierema    schedule 09.04.2016
comment
@Marko Есть ли более короткий путь?   -  person Naman    schedule 09.04.2016
comment
@Naman Это настолько коротко, насколько это возможно.   -  person Nathan Bierema    schedule 09.04.2016
comment
Это один лайнер, насколько коротким он вам нужен?   -  person Jonesopolis    schedule 09.04.2016
comment
Это двумерный массив или массив Jagged? если это двухмерный (или многомерный) массив, он уже сглажен.   -  person Hari Prasad    schedule 09.04.2016
comment
Какая? Однострочный текст недостаточно для вас?... Вам нужно четко расставить приоритеты.   -  person Jeff Mercado    schedule 09.04.2016
comment
Попробуйте это решение: gist.github.com/cirocorvino/3b387317be58b2b411b41ca039deed3e   -  person Ciro Corvino    schedule 24.08.2020


Ответы (2)


Возможно, я неправильно понимаю «кратчайший код», но я бы предложил использовать LINQ SelectMany и Distinct:

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

var flattenedUniqueValues = values.SelectMany(x => x).Distinct();
person devuxer    schedule 09.04.2016

Преобразование массива в шахматном порядке в одномерный массив просто и может быть выполнено в O(n) времени и n пространстве (где n - это сумма длин массива 2-го измерения), однако в вашем примере вы, кажется, удаляете повторяющиеся значения - это не сглаживание массива, но это все еще можно сделать за 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.

Существует еще одно решение, выполняющее 2 прохода самостоятельно: первый для определения размера вывода, затем второй проход для его генерации, что приведет к меньшему копированию: ровно 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;
person Dai    schedule 09.04.2016