J'ai cherché la différence entre Select
et SelectMany
mais je n'ai pas trouvé de réponse satisfaisante. J'ai besoin de connaître la différence lors de l'utilisation de LINQ To SQL, mais tous ceux que j'ai trouvés sont des exemples de tableaux standard.
Quelqu'un peut-il fournir un exemple LINQ To SQL?
SelectMany
aplatit les requêtes qui renvoient des listes de listes. Par exemple
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 });
Sélectionnez Many is like opération de jointure croisée en SQL où il prend le produit croisé.
Par exemple, si nous avons
Set A={a,b,c}
Set B={x,y}
Sélectionnez plusieurs peuvent être utilisés pour obtenir l'ensemble suivant
{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
Notez que nous prenons ici toutes les combinaisons possibles pouvant être faites à partir des éléments des ensembles A et B.
Voici un exemple LINQ que vous pouvez essayer
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 });
le mélange aura les éléments suivants dans la structure plate comme
{(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()
vous permet de réduire une séquence multidimensionnelle d'une manière qui nécessiterait sinon une seconde Select()
ou une boucle.
Plus de détails à ce sujet blog post .
Il y a plusieurs surcharges à SelectMany
. L'un d'eux vous permet de garder trace de toute relation entre parent et enfants tout en traversant la hiérarchie.
Exemple : supposons que vous ayez la structure suivante: League -> Teams -> Player
.
Vous pouvez facilement retourner une collection plate de joueurs. Cependant, vous risquez de perdre toute référence à l'équipe dont le joueur fait partie.
Heureusement, il existe une surcharge à cette fin:
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
};
L'exemple précédent est tiré de blog de Dan IK . Je vous recommande fortement d'y jeter un coup d'œil.
Je comprends que SelectMany fonctionne comme un raccourci de jointure.
Afin que vous puissiez:
var orders = customers
.Where(c => c.CustomerName == "Acme")
.SelectMany(c => c.Orders);
Select est une simple projection individuelle d'un élément source à un élément de résultat. Select-Many est utilisé lorsqu'il existe plusieurs clauses from dans une expression de requête: chaque élément de la séquence d'origine est utilisé pour générer une nouvelle séquence.
Certains SelectMany peuvent ne pas être nécessaires. 2 requêtes ci-dessous donnent le même résultat.
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)
Orders.Where(o=>o.Customer.Name=="Tom")
Pour une relation un à plusieurs,
from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
Sans être trop technique - base de données avec de nombreuses organisations, chacune avec de nombreux utilisateurs: -
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();
les deux renvoient le même Liste ApplicationUser pour l'organisation sélectionnée.
Le premier "projets" d'Organisation à Utilisateurs, le second interroge directement le tableau Utilisateurs.
Juste pour une autre vue qui pourrait aider certains programmeurs fonctionnels:
Select
est map
SelectMany
est bind
(ou flatMap
pour votre peuple Scala/Kotlin)Il est plus clair que la requête retourne une chaîne (un tableau de caractères):
Par exemple, si la liste 'Fruits' contient 'Apple'
'Select' renvoie la chaîne:
Fruits.Select(s=>s)
[0]: "Apple"
'SelectMany' aplatit la chaîne:
Fruits.SelectMany(s=>s)
[0]: 97 'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
Un autre exemple d'utilisation de SelectMany + Select pour accumuler des données d'objets de sous-tableau.
Supposons que nous ayons des utilisateurs avec leurs téléphones:
class Phone {
public string BasePart = "555-xxx-xxx";
}
class User {
public string Name = "Xxxxx";
public List<Phone> Phones;
}
Nous devons maintenant sélectionner les pièces de base de tous les téléphones de tous les utilisateurs:
var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();