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

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

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(); 

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

  • Напишите функцию, которая возвращает самый длинный палиндром в заданной строке
  • Проблема с укладкой коробки
  • Разница между примечаниями Big-O и Little-O
  • Быстрая сортировка Наихудший случай
  • Как получить пересечение между двумя массивами как новый массив?
  • Создайте список простых чисел до определенного числа
  • Пропустить Список против двоичного дерева поиска
  • Структура данных для загруженных кубиков?
  • Наименьшее общее число для 3 или более номеров
  • Как работает Math.Pow (и так далее)
  • Как проверить, является ли число палиндром?
  • Interesting Posts

    Ограничьте IE8 до одного окна (всегда используйте вкладки)

    Как можно делать USSD-запросы на Android?

    nth-child не отвечает classу

    Как я могу получить ячейку в Excel, чтобы автоматически регулировать ее высоту, чтобы она соответствовала содержимому завернутого текста?

    Пароль защищает определенный URL-адрес

    Как установить firefox в качестве браузера по умолчанию для всех новых пользователей?

    Переключить режим самолета в Android

    «Неверный» размер кадра / windows после переориентации в iPhone

    Как зашифровать файл с SD-карты с помощью AES на Android?

    (Контакт) не могут быть добавлены до тех пор, пока они не примут ваш запрос на контакт

    Какая папка App_Data используется в Visual Studio?

    Почему установка npm говорит, что у меня есть неудовлетворенные зависимости?

    Формат тела веб-службы RESTful

    Использование app.config в .Net Core

    Параллельный просмотр стороны частичного просмотра диалогового windows Jquery при нажатии кнопки «Сохранить»

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