私はSelect
とSelectMany
の違いを探してきましたが、適切な答えを見つけることができませんでした。 LINQ To SQLを使用するときの違いを学ぶ必要がありますが、私が見つけたのは標準的な配列の例だけです。
誰かがLINQ To SQLの例を提供できますか?
SelectMany
は、リストのリストを返すクエリを統合します。例えば
public class PhoneNumber
{
public string Number { get; set; }
}
public class Person
{
public IEnumerable<PhoneNumber> PhoneNumbers { get; set; }
public string Name { get; set; }
}
IEnumerable<Person> people = new List<Person>();
// Select gets a list of lists of phone numbers
IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers);
// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);
// And to include data from the parent in the result:
// pass an expression to the second parameter (resultSelector) in the overload:
var directory = people
.SelectMany(p => p.PhoneNumbers,
(parent, child) => new { parent.Name, child.Number });
Select manyはSQLの クロスジョイン操作に似ています それがクロス積をとるところ。
たとえば、
Set A={a,b,c}
Set B={x,y}
次のセットを取得するために使用できる多くの選択
{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
ここで、集合Aと集合Bの要素から作ることができるすべての可能な組み合わせを取ります。
これはあなたが試すことができるLINQの例です。
List<string> animals = new List<string>() { "cat", "dog", "donkey" };
List<int> number = new List<int>() { 10, 20 };
var mix = number.SelectMany(num => animals, (n, a) => new { n, a });
ミックスは以下のような平らな構造の要素を持ちます。
{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
var players = db.SoccerTeams.Where(c => c.Country == "Spain")
.SelectMany(c => c.players);
foreach(var player in players)
{
Console.WriteLine(player.LastName);
}
...
SelectMany()
を使用すると、多次元シーケンスを折りたたむことができます。そうしないと、2番目のSelect()
またはループが必要になります。
詳細はこちら ブログ投稿 で。
SelectMany
にはいくつかのオーバーロードがあります。そのうちの1つでは、階層を移動しながら、親と子の間の関係を追跡できます。
例 :League -> Teams -> Player
という構造になっているとします。
あなたは簡単にプレイヤーのフラットコレクションを返すことができます。しかし、あなたはその選手が所属するチームへの言及を失うかもしれません。
幸い、そのような目的のために過負荷があります:
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
};
前の例は DanのIK blog からの抜粋です。ぜひご覧ください。
私は、SelectManyが結合ショートカットのように機能することを理解しています。
だからあなたはできる:
var orders = customers
.Where(c => c.CustomerName == "Acme")
.SelectMany(c => c.Orders);
Selectは、ソース要素から結果要素への単純な一対一の投影です。クエリ式に複数のfrom句がある場合は、Select-Manyが使用されます。元のシーケンスの各要素は、新しいシーケンスを生成するために使用されます。
一部のSelectManyは必要ないかもしれません。以下の2つのクエリで同じ結果が得られます。
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)
Orders.Where(o=>o.Customer.Name=="Tom")
一対多の関係では、
from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
あまりにも技術的にならずに - 多くの組織を持ち、それぞれに多くのユーザーを持つデータベース -
var orgId = "123456789";
var userList1 = db.Organizations
.Where(a => a.OrganizationId == orgId)
.SelectMany(a => a.Users)
.ToList();
var userList2 = db.Users
.Where(a => a.OrganizationId == orgId)
.ToList();
両方とも 同じ - 選択された組織の/ ApplicationUserリストを返します。
組織からユーザーへの最初の "プロジェクト"、2番目のユーザーから直接ユーザーテーブルへのクエリを実行します。
機能的なプログラマーを助けるための別の見方をしてください。
Select
はmap
ですSelectMany
はbind
です(またはScala/Kotlinの人々の場合はflatMap
)クエリが文字列(charの配列)を返すと、より明確になります。
たとえば、リスト「フルーツ」に「アップル」が含まれているとします。
'Select'は文字列を返します。
Fruits.Select(s=>s)
[0]: "Apple"
'SelectMany'は文字列を平坦化します。
Fruits.SelectMany(s=>s)
[0]: 97 'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
サブ配列オブジェクトのデータを累積するためにSelectMany + Selectを使用する方法のもう1つの例。
ユーザーに電話をかけているとします。
class Phone {
public string BasePart = "555-xxx-xxx";
}
class User {
public string Name = "Xxxxx";
public List<Phone> Phones;
}
今、私たちはすべてのユーザーのすべての携帯電話のBasePartsを選択する必要があります。
var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();