web-dev-qa-db-fra.com

Différence entre Select et SelectMany

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?

955
Tarik

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

Démo en direct sur .NET Fiddle

1489
Mike Two

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)}
167

enter image description here

var players = db.SoccerTeams.Where(c => c.Country == "Spain")
                            .SelectMany(c => c.players);

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}
  1. De Gea
  2. Alba
  3. Costa
  4. Villa
  5. Busquets

...

107
AlejandroR

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 .

74
Michael Petrotta

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.

33
roland

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);
19
Nathan Koop

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.

13
Alexandr

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,

  1. si Démarrer à partir de "1", SelectMany est nécessaire, il aplatit les nombreux.
  2. si Démarrer à partir de "Plusieurs", SelectMany n'est pas nécessaire. (toujours en mesure de filtrer à partir de "1", c'est aussi plus simple que la requête de jointure standard ci-dessous)

from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
7
Rm558

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.

4
RickL

Juste pour une autre vue qui pourrait aider certains programmeurs fonctionnels:

  • Select est map
  • SelectMany est bind (ou flatMap pour votre peuple Scala/Kotlin)
2
Matt Klein

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'
2
Eric Bole-Feysot

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