Select ve SelectMany arasındaki fark


1073

Ben arasındaki farkı arama oldum Selectve SelectManyancak uygun bir cevap bulmak mümkün olmamıştır. LINQ To SQL kullanırken farkı öğrenmek gerekir ama tüm bulduğum standart dizi örnekleridir.

Birisi LINQ To SQL örneği sağlayabilir mi?



1
Kotlin'i biliyorsanız, harita aka C # Select ve flatMap aka C # SelectMany gibi koleksiyonlar için oldukça benzer uygulamalara sahiptir. Temelde koleksiyonlar için Kotlin std kütüphane genişletme fonksiyonları C # Linq kütüphanesine benzerlik gösterir.
Arsenius

Yanıtlar:


1620

SelectManyliste listelerini döndüren sorguları düzleştirir. Örneğin

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

.NET Fiddle'da Canlı Demo


1
İç içe yerleştirmeyle ilgili soru İç içe hiyerarşik bir yapıyı düzleştirmek için SelectMany'yi seçin.
Kızıl Bezelye


Ebeveynin sonuçları ile bir demo daha: dotnetfiddle.net/flcdCC
Evgeniy Kosjakov

keman bağlantısı için teşekkür ederim!
Aerin

197

Birçoğu, SQL'de çapraz ürünü aldığı çapraz birleştirme işlemi gibidir .
Örneğin,

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

Aşağıdaki seti almak için birçok seçim kullanılabilir

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

Burada, A kümesi ve B kümesi öğelerinden yapılabilecek tüm olası kombinasyonları aldığımızı unutmayın.

İşte deneyebileceğiniz bir LINQ örneği

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

karışım aşağıdaki gibi düz yapıda aşağıdaki öğelere sahip olacaktır:

{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}

4
Bunun eski olduğunu biliyorum, ama bunun için sana teşekkür etmek istedim, bu beni çok kurtardı! :) Bu kodlara da başvurmak yararlı olabilir: stackoverflow.com/questions/3479980/… Şerefe!
user3439065

4
SelectMany'nin böyle kullanılması gerekmez. Sadece bir işlevi de alma seçeneği vardır.
barlop

2
Bu nasıl olduğunu söylemek doğru olmadığını Bilmiyorum SelectMany olduğunu . Daha ziyade, bu kullanılabilecek bir yoldur SelectMany, ancak aslında bunu kullanmanın normal yolu değildir.
Dave Cousineau

1
Bu benim anlayabileceğim en basit cevaptı.
Chaim Eliyah

Ayrıca göstermeleri halinde iyi olurdu Wheresonra SelectMany koşulunu
Nitin Kt

126

resim açıklamasını buraya girin

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

...


9
büyük örnek veri
ben_mj

1
Bu yanıtı tamamlamak için seçmek için bir örnek ekleyebilir misiniz :)
Harry

73

SelectMany()çok boyutlu bir diziyi, aksi takdirde bir saniye Select()veya döngü gerektirecek şekilde daraltmanıza olanak tanır .

Bu blog gönderisinde daha fazla ayrıntı .


Ama birincisi Enumerables Tipi Çocuklara geri dönüş İkinci örnek dönüş Tipi Ebeveynler? Aslında biraz kafam karıştı, biraz daha açar mısın?
Tarik

Aslında başka türlü. İkincisi, numaralandırılabilir hiyerarşiyi tamamen düzleştirecek, böylece Çocukları geri alacaksınız. Eklediğim bağlantıdaki makaleyi deneyin, bunun işe yarayıp yaramadığına bakın.
Michael Petrotta

İlki yasal görünmüyor. Bence poster karıştı. İkincisi, sayısız ebeveynleri iade edecektir.
mqp

Teşekkürler, aslında evet örnekler biraz kafa karıştırıcıydı :) ama bana yardım etmeye çalıştığın için tekrar teşekkürler.
Tarik

37

Birkaç aşırı yükleme var SelectMany. Bunlardan biri, hiyerarşiyi dolaşırken ebeveyn ve çocuklar arasındaki herhangi bir ilişkiyi izlemenize izin verir.

Örnek : Aşağıdaki yapıya sahip varsayalım: League -> Teams -> Player.

Düz bir oyuncu koleksiyonuna kolayca geri dönebilirsiniz. Ancak, oyuncunun üyesi olduğu takıma herhangi bir referans kaybedebilirsiniz.

Neyse ki böyle bir amaç için aşırı yük var:

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

Önceki örnek Dan'ın IK blogundan alınmıştır . Şuna bir göz atmanızı şiddetle tavsiye ederim.


19

SelectManyBirleştirme kısayolu gibi çalışmayı anlıyorum .

Böylece yapabilirsiniz:

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

Sağlanan örnek çalışıyor, ancak SelectMany tam olarak bir birleştirme gibi çalışmıyor. Birleştirme, orijinal tablonun herhangi bir alanının artı birleştirilmiş tablonun herhangi bir alanının "kullanılmasına" izin verir. Ancak burada, orijinal tabloya eklenmiş bir listenin nesnesini belirtmeniz gerekir. Örneğin, .SelectMany(c => new {c.CompanyName, c.Orders.ShippedDate});işe yaramaz. SelectMany, liste listesini düzleştiriyor ve sonuç için içerilen listelerin herhangi birini (ancak her seferinde bir tane) seçebilirsiniz. Karşılaştırma için: Linq .
Matt

13

Select, kaynak öğeden sonuç öğesine basit bire bir projeksiyondur. Select- Many, bir sorgu ifadesinde birden çok cümle olduğunda kullanılır: orijinal dizideki her öğe yeni bir dizi oluşturmak için kullanılır.


7

Bazı SelectMany gerekli olmayabilir. Aşağıdaki 2 sorgu aynı sonucu verir.

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

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

1-Çok-ilişki için,

  1. "1" 'den Başla, SelectMany gerekiyorsa, çoğunu düzleştirir.
  2. "Birçok" dan Başla, SelectMany gerekli değildir. ( yine de "1" den filtrelenebilir , ayrıca bu standart birleştirme sorgusunun altında olduğundan daha basittir)

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

4

Çok teknik olmadan - her biri birçok Kullanıcı ile birçok Organizasyon veritabanı: -

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

her ikisi de seçilen Kuruluş için aynı ApplicationUser listesini döndürür .

Kuruluştan Kullanıcılara ilk "projeler", ikincisi Kullanıcılar tablosunu doğrudan sorgular.


3

Sorgu bir dize (karakter dizisi) döndürdüğünde daha açıktır:

Örneğin, 'Meyveler' listesi 'elma' içeriyorsa

'Seç' dizeyi döndürür:

Fruits.Select(s=>s) 

[0]: "apple"

'SelectMany' dizeyi düzleştirir:

Fruits.SelectMany(s=>s)

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

2

Sadece bazı fonksiyonel programcılara yardımcı olabilecek alternatif bir görünüm için:

  • Select dır-dir map
  • SelectManyolduğu bind(ya flatMapda Scala / Kotlin kişilik)

2

Bu örneği düşünün:

        var array = new string[2]
        {
            "I like what I like",
            "I like what you like"
        };
        //query1 returns two elements sth like this:
        //fisrt element would be array[5]  :[0] = "I" "like" "what" "I" "like"
        //second element would be array[5] :[1] = "I" "like" "what" "you" "like"
        IEnumerable<string[]> query1 = array.Select(s => s.Split(' ')).Distinct();

        //query2 return back flat result sth like this :
        // "I" "like" "what" "you"
        IEnumerable<string> query2 = array.SelectMany(s => s.Split(' ')).Distinct();

Gördüğünüz gibi "Select" gibi "I" veya "like" gibi yinelenen değerler kaldırıldı çünkü "SelectMany" birden çok diziyi düzleştiriyor ve projelendiriyor. Ancak query1, dize dizilerinin sırasını döndürür. ve sorgu1'de (birinci ve ikinci öğe) iki farklı dizi bulunduğundan, hiçbir şey kaldırılmaz.


şimdi sonu ve devlet de .Distinct () içerecek şekilde muhtemelen daha iyi "I" " "ne" "I" "gibi" "I" "gibi" "ne" "sen" "" gibi benzeri" çıkışı
Prof

1

Alt dizi nesneleri verilerini toplamak için SelectMany + Select'in nasıl kullanılabileceğine bir örnek daha.

Telefonları olan kullanıcılarımız olduğunu varsayalım:

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

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

Şimdi tüm telefonların tüm kullanıcıların BaseParts'larını seçmemiz gerekiyor:

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

Hangisinin daha iyi olduğunu düşünüyorsun? Sevgiler ya dausersArray.SelectMany(ua => ua.Phones.Select(p => p.BasePart))
Michael Best

-1

Test için başlatılmış küçük bir koleksiyona sahip bir kod örneği:

class Program
{
    static void Main(string[] args)
    {
        List<Order> orders = new List<Order>
        {
            new Order
            {
                OrderID = "orderID1",
                OrderLines = new List<OrderLine>
                {
                    new OrderLine
                    {
                        ProductSKU = "SKU1",
                        Quantity = 1
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU2",
                        Quantity = 2
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU3",
                        Quantity = 3
                    }
                }
            },
            new Order
            {
                OrderID = "orderID2",
                OrderLines = new List<OrderLine>
                {
                    new OrderLine
                    {
                        ProductSKU = "SKU4",
                        Quantity = 4
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU5",
                        Quantity = 5
                    }
                }
            }
        };

        //required result is the list of all SKUs in orders
        List<string> allSKUs = new List<string>();

        //With Select case 2 foreach loops are required
        var flattenedOrdersLinesSelectCase = orders.Select(o => o.OrderLines);
        foreach (var flattenedOrderLine in flattenedOrdersLinesSelectCase)
        {
            foreach (OrderLine orderLine in flattenedOrderLine)
            {
                allSKUs.Add(orderLine.ProductSKU);
            }
        }

        //With SelectMany case only one foreach loop is required
        allSKUs = new List<string>();
        var flattenedOrdersLinesSelectManyCase = orders.SelectMany(o => o.OrderLines);
        foreach (var flattenedOrderLine in flattenedOrdersLinesSelectManyCase)
        {
            allSKUs.Add(flattenedOrderLine.ProductSKU);
        }

       //If the required result is flattened list which has OrderID, ProductSKU and Quantity,
       //SelectMany with selector is very helpful to get the required result
       //and allows avoiding own For loops what according to my experience do code faster when
       // hundreds of thousands of data rows must be operated
        List<OrderLineForReport> ordersLinesForReport = (List<OrderLineForReport>)orders.SelectMany(o => o.OrderLines,
            (o, ol) => new OrderLineForReport
            {
                OrderID = o.OrderID,
                ProductSKU = ol.ProductSKU,
                Quantity = ol.Quantity
            }).ToList();
    }
}
class Order
{
    public string OrderID { get; set; }
    public List<OrderLine> OrderLines { get; set; }
}
class OrderLine
{
    public string ProductSKU { get; set; }
    public int Quantity { get; set; }
}
class OrderLineForReport
{
    public string OrderID { get; set; }
    public string ProductSKU { get; set; }
    public int Quantity { get; set; }
}

-2

SelectManyBir aşağı yöntem darbelere IEnumerable<IEnumerable<T>>bir halinde IEnumerable<T>, komünizm gibi, her eleman (aptal biri bir dahi bir aynı haklara sahiptir) aynı şekilde davranış göstermiştir edilir.

var words = new [] { "a,b,c", "d,e", "f" };
var splitAndCombine = words.SelectMany(x => x.Split(','));
// returns { "a", "b", "c", "d", "e", "f" }

-5

Sanırım anlamanın en iyi yolu bu.

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

Çarpım Tablosu örneği.


4
"En iyinin" anlamı dramatik bir şekilde değiştiğinde
Vahid Amiri

2
yani bu u düşünüyorum en iyi yolu ?? o zaman zor düşünme yolu nedir ??
Syed Ali
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.