Różnica między Select i SelectMany

Szukałem różnicy między Select i SelectMany, ale nie byłem w stanie znaleźć odpowiedniej odpowiedzi. Muszę nauczyć się różnicy przy użyciu LINQ do SQL, ale wszystko, co znalazłem, to standardowe przykłady tablic.

Czy ktoś może podać przykład LINQ do SQL?

Author: Jeeped, 2009-06-06

13 answers

SelectMany spłaszcza zapytania zwracające listy list. Na przykład

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

Demo Live na. Net

 1320
Author: Mike Two,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 10:23:27

Select many jest jak operacja łączenia krzyżowego w SQL gdzie przyjmuje iloczyn krzyżowy.
Na przykład jeśli mamy

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

Select many może być użyty do uzyskania następującego zestawu

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

Zauważ, że tutaj bierzemy wszystkie możliwe kombinacje, które mogą być wykonane z elementów zbioru a i zbioru B.

Oto przykład LINQ, który możesz wypróbować

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

Mieszanka będzie miała następujące elementy w strukturze płaskiej jak

{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
 148
Author: Sriwantha Attanayake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-12 12:21:41

Tutaj wpisz opis obrazka

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

...

 87
Author: AlejandroR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-28 17:43:51

SelectMany() pozwala zwinąć wielowymiarową sekwencję w sposób, który w przeciwnym razie wymagałby drugiej {[1] } lub pętli.

Więcej szczegółów na tym blogu .

 67
Author: Michael Petrotta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 16:17:35

Istnieje kilka przeciążeń SelectMany. Jeden z nich pozwala na śledzenie wszelkich relacji między rodzicem a dziećmi podczas przechodzenia przez hierarchię.

przykład: Załóżmy, że masz następującą strukturę: League -> Teams -> Player.

Możesz łatwo zwrócić płaską kolekcję graczy. Możesz jednak stracić wszelkie odniesienia do drużyny, w której gracz jest częścią.

Na szczęście jest przeciążenie w takim celu:

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

Poprzedni przykład pochodzi z Dan ' s IK blog . Zdecydowanie polecam rzucić na to okiem.

 32
Author: roland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-12 12:23:16

Rozumiem, że SelectMany działa jak skrót join.

Więc możesz:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);
 18
Author: Nathan Koop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-13 11:10:36

Select jest prostą projekcją jeden do jednego od elementu źródłowego do elementu wynikowego. Wybierz- Wiele jest używane, gdy w wyrażeniu zapytania znajduje się wiele klauzul from: każdy element oryginalnej sekwencji jest używany do generowania nowej sekwencji.

 12
Author: Alexandr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-25 09:32:02

Niektóre SelectMany mogą nie być konieczne. Poniżej 2 zapytań daje taki sam wynik.

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

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

Dla relacji 1 do wielu,

  1. jeśli zaczyna się od" 1", SelectMany jest potrzebny, to spłaszcza wiele.
  2. jeśli zaczyna się od "Many", SelectMany nie jest potrzebne. (nadal można filtrować z "1" , również jest to prostsze niż poniżej standardowego zapytania join)

from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
 7
Author: Rm558,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 20:23:58

Bez zbytniego technicznego-baza danych z wieloma organizacjami, każda z wieloma użytkownikami: -

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

Both return The same ApplicationUser list for the selected Organization.

Pierwszy "projekty" od organizacji do użytkowników, drugi zapytuje bezpośrednio tabelę użytkowników.

 3
Author: RickL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 15:46:30

Tylko dla alternatywnego widoku, który może pomóc niektórym funkcjonalnym programistom:

  • Select jest map
  • SelectMany jest bind (lub flatMap dla Twoich ludzi Scala / Kotlin)
 2
Author: Matt Klein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 07:47:46

Jest bardziej jasne, gdy zapytanie zwraca łańcuch znaków (tablicę znaków):

Na przykład, jeśli lista "owoce" zawiera "jabłko"

'Select' zwraca ciąg znaków:

Fruits.Select(s=>s) 

[0]: "apple"

'SelectMany' spłaszcza łańcuch:

Fruits.SelectMany(s=>s)

[0]: 97  'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
 1
Author: Eric Bole-Feysot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 14:59:06

Jeszcze jeden przykład użycia SelectMany + Select do gromadzenia danych obiektów podrzędnych.

Załóżmy, że mamy użytkowników z telefonami:

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

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

Teraz musimy wybrać podstawowe części wszystkich telefonów wszystkich użytkowników:

var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
 0
Author: KEMBL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 11:40:47

Myślę, że to najlepszy sposób na zrozumienie.

            var query =
            Enumerable
                .Range(1, 10)
                .SelectMany(ints => Enumerable.Range(1, 10), (a, b) => $"{a} * {b} = {a * b}")
                .ToArray();

        Console.WriteLine(string.Join(Environment.NewLine, query));

        Console.Read();

Przykład tablic mnożenia.

 -3
Author: user5966157,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-23 02:11:25