Linq для вложенной петли
У меня есть цикл следующим образом:
foreach(x in myColl)
{
foreach(var y in x.MyList)
{
result.Add(x.MyKey + y)
}
}
Это означает, что в моем внутреннем цикле мне нужен доступ к свойству текущего внешнего элемента.
Я ищу оператор LINQ, но я не уверен в этом. Я попробовал это, используя
result = myColl
.SelectMany(x => x.MyList)
.SelectMany(x => /* how to get the key of the outer loop here */ + x)
Ответы
Ответ 1
Это легко с выражениями запроса:
(from x in myColl
from y in x.MyList
select x.MyKey + y).ToList()
Это работает, потому что это означает:
myColl
.SelectMany(x => x.MyList.Select(item => new { List = x, Item = item }))
.Select(x => ...) //rest of the query, whatever you like
Ключ должен содержать как список, так и элементы списка. Проведите их через запрос с использованием анонимного типа (или любого другого контейнера).
Ответ 2
Существует перегрузка SelectMany, которая позволяет получить доступ к элементу "parent".
ListOfList.SelectMany(list = > list.InnerList, (lst, element) = > HandleInnerListAndElementFromIt (lst, element))
result = myColl.SelectMany(x => x.MyList,(x1,x2)=>DoSomething(x1,x2));
EDIT Добавлено:
Для вашего конкретного примера это выглядит так:
result = myColl.SelectMany(x=>x.MyList,(x,y)=>x.MyKey+y));
Обратите внимание, что для вызова метода SelectMany есть два лямбда-параметра.
Первая лямбда возьмет "x" и вернет новый Enumerable. х = > x.MyList
Вторая лямбда принимает "x" и "y" и создает новый результат. (х, у) = > x.MyKey + у
Ответ 3
Это когда я лично предпочитаю синтаксис запроса
var result = from x in myCol1
from y in x.MyList
select x.MyKey + y;
Ответ 4
Моя коллекция Лиг, Команд и Игроков имеет следующую структуру:
![enter image description here]()
Эта самая базовая версия дает вам полную коллекцию IEnumerable всех команд во всех лигах.
var allTeams = from t in leagues.
SelectMany( l => l.Teams )
select t;
Вы можете связать вызовы SelectMany вместе, чтобы погрузиться в иерархию настолько глубоко, насколько вы хотите. Это возвращает IEnumerable всех игроков во всех лигах и командах.
var allPlayers = from p in leagues
.SelectMany( l => l.Teams )
.SelectMany( t => t.Players )
select p;
И, конечно же, вы можете добавить критерии условия where для дальнейшего уточнения, какие игроки вы получаете сейчас, когда вы работаете с фиксированным списком игроков.
var onlyYoungPlayers = from p in leagues
.SelectMany( l => l.Teams )
.SelectMany( t => t.Players )
where p.Age < 30
select p;
Вот хороший способ связать Where() между вызовами SelectMany(), чтобы получить всех игроков только из определенных команд.
var players = leagues.SelectMany( l => l.Teams )
.Where( t => t.NumberOfWins > 2 )
.SelectMany( t => t.Players )
.Where( p => p.HomeState == "CA" )
.Select( p => p );
3-я и 4-я перегрузки метода SelectMany() с дополнительным параметром "селектор результата" требуют более подробного объяснения. Я рассматриваю этот дополнительный параметр селектора результата как вспомогательный объект, чтобы помочь вам узнать отношения между родительской и дочерней коллекциями. Скажем, вам нужна коллекция результатов, которая будет не только иметь полный список команд, соответствующих некоторым критериям во всех лигах, но и знать, в какую лигу входят команды. Если вы используете один из указанных выше запросов, вы получите полный список Командные объекты, но потеряли связь с тем, из какой они Лиги. (Иногда в вашей объектной модели есть "обратные ссылки" для перехода от дочернего объекта к их родителю, что делает ненужным использование этого селектора результатов, но вы не всегда имеете это преимущество.) Селектор результатов - это промежуточный объект, доступный в области действия запроса, чтобы дать вам необходимую информацию, и вам решать, какие данные вам нужны в селекторе результатов, чтобы помочь вам. Вот пример:
var teamsAndTheirLeagues = from helper in leagues
.SelectMany( l => l.Teams, ( league, team )
=> new { league, team } )
where helper.team.Players.Count > 2
&& helper.league.Teams.Count < 10
select new { LeagueID = helper.league.ID, Team = helper.team };
Таким образом, вспомогательный объект создается из Func <> с двумя аргументами, который берет объект из родительской коллекции и объект из дочерней коллекции, которые становятся парными во время обработки запроса, и вы можете делать с ними все, что захотите - Im просто делать что-то простое, что создает новый анонимный тип со встроенными в них объектами, что дает мне возможность использовать эти данные в предложении where, а также в результатах запроса. (Примечание: вы можете просто "выделить" весь вспомогательный объект в последней строке запроса)
Я полагаю, вы могли бы взглянуть на эту ссылку, поскольку я прочитал эту статью и обнаружил, что она почти полна, насколько это понятие касается.
http://blogs.interknowlogy.com/2008/10/10/use-linqs-selectmany-method-to-flatten-collections/