Как «застегнуть» или «повернуть» переменное количество списков?

Если у меня есть список, содержащий произвольное количество списков, например:

var myList = new List<List>() { new List() { "a", "b", "c", "d" }, new List() { "1", "2", "3", "4" }, new List() { "w", "x", "y", "z" }, // ...etc... }; 

… есть ли какой-либо способ «застегнуть» или «повернуть» списки в нечто подобное?

 { { "a", "1", "w", ... }, { "b", "2", "x", ... }, { "c", "3", "y", ... }, { "d", "4", "z", ... } } 

Очевидным решением было бы сделать что-то вроде этого:

 public static IEnumerable<IEnumerable> Rotate(this IEnumerable<IEnumerable> list) { for (int i = 0; i  x.Count()); i++) { yield return list.Select(x => x.ElementAt(i)); } } // snip var newList = myList.Rotate(); 

… но мне было интересно, есть ли более чистый способ сделать это, используя linq или иначе?

7 Solutions collect form web for “Как «застегнуть» или «повернуть» переменное количество списков?”

Вы можете свернуть собственный экземпляр ZipMany, который вручную выполняет итерацию каждого из перечислений. Вероятно, это будет лучше для больших последовательностей, чем те, которые используют GroupBy после проецирования каждой последовательности:

 public static IEnumerable ZipMany( IEnumerable> source, Func, TResult> selector) { // ToList is necessary to avoid deferred execution var enumerators = source.Select(seq => seq.GetEnumerator()).ToList(); try { while (true) { foreach (var e in enumerators) { bool b = e.MoveNext(); if (!b) yield break; } // Again, ToList (or ToArray) is necessary to avoid deferred execution yield return selector(enumerators.Select(e => e.Current).ToList()); } } finally { foreach (var e in enumerators) e.Dispose(); } } 

Вы можете сделать это, используя расширение Select , используя Func :

 var rotatedList = myList.Select(inner => inner.Select((s, i) => new {s, i})) .SelectMany(a => a) .GroupBy(a => ai, a => as) .Select(a => a.ToList()).ToList(); 

Это даст вам другой List> .

Сломать

 .Select(inner => inner.Select((s, i) => new {s, i})) 

Для каждого внутреннего списка мы проецируем содержимое списка на новый анонимный объект с двумя свойствами: s , строковое значение и i индекс этого значения в исходном списке.

 .SelectMany(a => a) 

Мы сглаживаем результат до одного списка

 .GroupBy(a => ai, a => as) 

Мы группируем по свойству i нашего анонимного объекта (напомним, что это индекс) и выбираем свойство s как наши значения (только строка).

 .Select(a => a.ToList()).ToList(); 

Для каждой группы мы перечислили перечислимый список и другой список для всех групп.

Как насчет использования SelectMany и GroupBy с некоторыми индексами?

 // 1. Project inner lists to a single list (SelectMany) // 2. Use "GroupBy" to aggregate the item's based on order in the lists // 3. Strip away any ordering key in the final answer var query = myList.SelectMany( xl => xl.Select((vv,ii) => new { Idx = ii, Value = vv })) .GroupBy(xx => xx.Idx) .OrderBy(gg => gg.Key) .Select(gg => gg.Select(xx => xx.Value)); 

От LinqPad:

мы группируем элементы

Вот неэффективный вариант, основанный на трансформации матрицы:

 public static class Ext { public static IEnumerable> Rotate( this IEnumerable> src) { var matrix = src.Select(subset => subset.ToArray()).ToArray(); var height = matrix.Length; var width = matrix.Max(arr => arr.Length); T[][] transpose = Enumerable .Range(0, width) .Select(_ => new T[height]).ToArray(); for(int i=0; i 

Взгляните на проект linqlib на codeplex , он имеет функцию поворота, которая делает именно то, что вам нужно.

Вы можете конденсироваться for циклов, используя Range :

 var result = Enumerable.Range(0, myList.Min(l => l.Count)) .Select(i => myList.Select(l => l[i]).ToList()).ToList(); 
 (from count in Range(myList[0].Count) select new List( from count2 in Range(myList.Count) select myList[count2][count]) ).ToList(); 

Это некрасиво, но я думаю, что это сработает.

  • Поиск максимума для каждого windows размера k в массиве
  • Пропустить Список против двоичного дерева поиска
  • Найти первый повторный символ в строке
  • Как найти k-й наибольший элемент в несортированном массиве длины n в O (n)?
  • Рекурсия или итерация?
  • Объединить данные гироскопа и акселерометра
  • Программа для печати перестановок заданных элементов
  • Перемешать список, гарантируя, что элемент не останется в одном положении
  • Детали реализации оборудования с плавающей запятой
  • Как вы проверяете двоичное дерево поиска?
  • Двоичный поиск в массиве
  • Interesting Posts

    Текущий узел или узел контекста в XSLT / XPath?

    Что такое имена столбцов DataTable с точками, что делает их непригодными для управления DataGrid WPF?

    Обнаружение, если событие вставки произошло в расширенном текстовом поле

    Какие шаблоны дизайна используются на Android?

    Почему я не могу создать папку с именем COM1

    Как установить лимиты для осей в графиках ggplot2 R?

    Java: зачем вам нужно указывать ‘f’ в streamовом литерале?

    Почему минималистский, например, Haskell quicksort не «истинный» quicksort?

    MD5 hash с солью для хранения пароля в БД в C #

    Что означают запятые и пробелы в нескольких classах в CSS?

    Настройка маршрутизации Windows 7 между 2 сетями

    Как заблокировать видео html5 в системе

    Не удается удалить бесконечно повторяющуюся папку в папке в папке и т. Д.

    Конденсация в несколько страниц PDF на листе, через командную строку

    Исключение grep из списка процессов

    Давайте будем гением компьютера.