Как мне объединить несколько IEnumerables из T

Данный....

Public MasterList as IEnumerable(Of MasterItem)
Public Class MasterItem(Of T) 
    Public SubItems as IEnumerable(Of T)
End Class 

Мне нужен один IEnumerable(Of T), который будет перебирать все подэлементы всех основных элементов в MasterList.

Я хотел бы думать, что для этого есть средство Linq или метод расширения, который я пропускаю. Мне нужен механизм, который работает в VB9 (2008) и, следовательно, не использует Yield.


person Rory Becker    schedule 30.06.2009    source источник


Ответы (5)


Вы ищете SelectMany()?

MasterList.SelectMany(master => master.SubItems)

Извините за C#, не знаю VB.

person Per Erik Stendahl    schedule 30.06.2009
comment
Фантастика... Абсолютно люблю StackOverflow... Тесное взаимодействие между вами и Оливером Ханаппи.... Очки начисляются просто за немного более понятный код (с очень небольшим отрывом). - person Rory Becker; 30.06.2009
comment
Спасибо. Довольно сложно заработать репутацию на этом сайте, когда ты соревнуешься с сотней других парней в течение первых 5 минут после того, как задан вопрос. :-D - person Per Erik Stendahl; 30.06.2009
comment
Версия FWIW VB.Net: MasterList.SelectMany (функция (мастер) master.SubItems) - person Rory Becker; 30.06.2009
comment
Если кто-то хочет увидеть полный пример на С#, я разместил вопрос до того, как нашел этот. Номер вопроса — 1222846. Я не знаю, как сделать ссылку на него отсюда. - person Robin Robinson; 03.08.2009

Вы можете добиться этого с помощью Linq с помощью SelectMany

Код С#

masterLists.SelectMany(l => l.SubItems);


С наилучшими пожеланиями

person Oliver Hanappi    schedule 30.06.2009
comment
Спасибо и тебе, Оливер. Жаль, что я не мог разделить очки ... Тем не менее, проголосовал за вас. :) - person Rory Becker; 30.06.2009
comment
Нет проблем ^^ По крайней мере, теперь я могу оставлять комментарии :) - person Oliver Hanappi; 30.06.2009

Enumerable.SelectMany является ключом к монаде IEnumerable, так же как его эквивалент в Haskell, concatMap, является ключом к монаде списка Haskell.

Как оказалось, ваш вопрос касается самого глубокого аспекта информатики.

Вы должны быть осторожны с формулировкой, потому что Aggregate означает что-то очень отличное от SelectMany - даже противоположное. Aggregate объединяет IEnumerable значений в одно значение (возможно, другого типа), а SelectMany un объединяет IEnumerable значений в еще большее количество значений (возможно, другого типа).

person yfeldblum    schedule 01.07.2009
comment
+1 для фона, хотя в некотором смысле Aggregate и SelectMany похожи тем, что они выполняют функцию несколько раз, в зависимости от длины входного списка, и возвращают один объект (который оказывается другим списком для SelectMany, но Aggregate также может вернуть список). Настоящая противоположность Aggregate обычно называется Unfold, и в BCL пока нет функции для этого. - person Daniel Earwicker; 01.07.2009
comment
Это правда, fold и unfold являются инверсиями, но я имел в виду немного другое под словом «противоположное», а именно: Aggregate берет много и объединяет в одно, а SelectMany берет каждое и раскомбинирует во многие. Кроме того, я бы не согласился с тем, что SelectMany возвращает один объект — хотя в каком-то смысле это правда, это неверно в смысле монады IEnumerable, где у вас есть списки, идущие к спискам, идущие к спискам (как это происходит с Select, Where, Take, Drop, OrderBy, GroupBy, SelectMany и т. д.). - person yfeldblum; 01.07.2009
comment
@Justice.. Мне очень интересно то, что вы здесь сказали... Это правда, что сначала меня привлекла Aggregate, потому что с чисто английской точки зрения казалось, что это то, что мне нужно. Теперь мне любопытно, что предоставляет Aggregate... Возможно, вы могли бы указать мне ссылку, которая дает более подробную информацию... Я хотел бы увидеть пример. еще раз спасибо... Очень полезно. - person Rory Becker; 02.07.2009

Просто чтобы дать истинные ответы VB.NET:

' Identical to Per Erik Stendahl's and Oliver Hanappi's C# answers
Dim children1 = MasterList.SelectMany(Function(master) master.SubItems)

' Using VB.NET query syntax
Dim children2 = From master In MasterList, child in master.SubItems Select child

' Using Aggregate, as the question title referred to
Dim children3 = Aggregate master In MasterList Into SelectMany(master.SubItems)

Все они компилируются в один и тот же IL, за исключением того, что для children2 требуется эквивалент Function(master, child) child.

person Mark Hurd    schedule 05.02.2014

Я знаю, что в С# есть оператор yield для циклов. Просто повторите и yield return каждый подэлемент рекурсивно. Судя по всему, yield для VB нет, извините.

person Community    schedule 30.06.2009
comment
С удовольствием.... К сожалению... VB.Net 2008 :( Один из его недостатков - отсутствие такого оператора. - person Rory Becker; 30.06.2009