it-swarm.com.de

Unterschied zwischen Select und SelectMany

Ich habe den Unterschied zwischen Select und SelectMany gesucht, aber keine passende Antwort gefunden. Ich muss den Unterschied lernen, wenn ich LINQ To SQL verwende, aber ich habe nur Standard-Array-Beispiele gefunden.

Kann jemand ein LINQ To SQL-Beispiel bereitstellen?

955
Tarik

SelectMany reduziert Abfragen, die Listen mit Listen zurückgeben. Zum Beispiel

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

Live Demo auf .NET Fiddle

1489
Mike Two

Wählen Sie viele ist wie Cross-Join-Operation in SQL , wo es das Cross-Produkt nimmt.
Zum Beispiel, wenn wir haben

Set A={a,b,c}
Set B={x,y}

Wählen Sie viele aus, um den folgenden Satz zu erhalten

{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }

Beachten Sie, dass wir hier alle möglichen Kombinationen nehmen, die aus den Elementen von Satz A und Satz B gemacht werden können.

Hier ist ein LINQ-Beispiel, das Sie ausprobieren können

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

der Mix wird folgende Elemente in flacher Struktur haben

{(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

Mit SelectMany() können Sie eine mehrdimensionale Sequenz so komprimieren, dass andernfalls eine zweite Select() oder Schleife erforderlich wäre.

Weitere Details dazu Blogpost .

74

SelectMany weist mehrere Überladungen auf. Mit einem von ihnen können Sie die Beziehung zwischen Eltern und Kindern verfolgen, während Sie die Hierarchie durchlaufen.

Beispiel : Angenommen, Sie haben die folgende Struktur: League -> Teams -> Player.

Sie können ganz einfach eine flache Sammlung von Spielern zurückgeben. Sie können jedoch den Bezug zu der Mannschaft verlieren, der der Spieler angehört.

Zum Glück gibt es eine Überlastung für diesen Zweck:

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

Das vorherige Beispiel stammt aus Dans IK Blog . Ich empfehle Ihnen dringend, sich das anzuschauen.

33
roland

Ich verstehe SelectMany, um wie eine Verbindungsverknüpfung zu arbeiten.

Also kannst du:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);
19
Nathan Koop

Select ist eine einfache Eins-zu-Eins-Projektion vom Quellelement zum Ergebniselement. Select-Many wird verwendet, wenn ein Abfrageausdruck mehrere from-Klauseln enthält: Jedes Element in der ursprünglichen Sequenz wird zum Generieren einer neuen Sequenz verwendet.

13
Alexandr

Einige SelectMany sind möglicherweise nicht erforderlich. Unter 2 Abfragen erhalten Sie das gleiche Ergebnis.

Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)

Orders.Where(o=>o.Customer.Name=="Tom")

Für 1-to-Many-Beziehung,

  1. wenn SelectMany benötigt wird, wenn Sie mit "1" beginnen, werden die vielen reduziert.
  2. wenn Sie mit "Viele" beginnen, wird SelectMany nicht benötigt. (kann immer noch nach "1" filtern, auch dies ist einfacher als unter der Standard-Join-Abfrage)

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

Ohne zu technisch zu werden - Datenbank mit vielen Organisationen mit jeweils vielen Benutzern: -

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

beide geben dasselbe ApplicationUser-Liste für die ausgewählte Organisation zurück.

Das erste "Projekt" von Organisation zu Benutzer, das zweite fragt die Benutzertabelle direkt ab.

4
RickL

Nur für eine alternative Ansicht, die einigen funktionalen Programmierern da draußen helfen kann:

  • Select ist map
  • SelectMany ist bind (oder flatMap für Ihre Scala/Kotlin-Leute)
2
Matt Klein

Es ist klarer, wenn die Abfrage eine Zeichenfolge (ein Array von Zeichen) zurückgibt:

Zum Beispiel, wenn die Liste 'Früchte' 'Apfel' enthält

'Select' liefert den String:

Fruits.Select(s=>s) 

[0]: "Apple"

'SelectMany' verflacht den String:

Fruits.SelectMany(s=>s)

[0]: 97  'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
2

Ein weiteres Beispiel, wie SelectMany + Select verwendet werden kann, um Daten von Subarray-Objekten zu akkumulieren.

Angenommen, wir haben Benutzer mit folgenden Telefonen:

class Phone { 
    public string BasePart = "555-xxx-xxx"; 
}

class User { 
    public string Name = "Xxxxx";
    public List<Phone> Phones; 
}

Jetzt müssen wir die BaseParts aller Telefone aller Benutzer auswählen:

var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
1
KEMBL