चयन और SelectMany के बीच अंतर


1071

मैं के बीच का अंतर खोज कर रहा है Selectऔर SelectManyलेकिन मैं एक उपयुक्त जवाब खोजने के लिए नहीं कर पाए हैं। लाइनक्यू टू एसक्यूएल का उपयोग करते समय मुझे अंतर सीखने की जरूरत है लेकिन मैंने पाया है कि सभी मानक सरणी उदाहरण हैं।

क्या कोई SQL उदाहरण के लिए LINQ प्रदान कर सकता है?


8
आप एक समारोह के साथ SelectMany के लिए कोड में देख सकते हैं, या दो कार्यों के साथ referencesource.microsoft.com/#System.Core/System/Linq/...
barlop

1
यदि आप कोटलिन से परिचित हैं, तो यह संग्रह उर्फ ​​सी # सिलेक्ट और फ्लैटपाइप उर्फ ​​सी # सिलेक्टनी के रूप में संग्रह के लिए काफी समान कार्यान्वयन है। मूल रूप से संग्रह के लिए कोटलिन std पुस्तकालय विस्तार कार्यों में C # Linq पुस्तकालय की समानता है।
आर्सेनियस

जवाबों:


1618

SelectManyसूचियों की सूची को लौटाने वाले प्रश्नों को समतल करता है। उदाहरण के लिए

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 फिडल पर लाइव डेमो


1
नेस्टेड पदानुक्रमित संरचना को समतल करने के लिए SelectMany के घोंसले के शिकार से संबंधित प्रश्न
लाल मटर

1
ResultSelector को समझने के लिए और अधिक लिंक नीचे में मदद करता है blogs.interknowlogy.com/2008/10/10/...
जमीर

माता-पिता के परिणामों के साथ एक और डेमो: dotnetfiddle.net/flcdCC
इवगेनी कोसजाकोव

फिडेल लिंक के लिए धन्यवाद!
एरिन

197

कई का चयन करें एसक्यूएल में क्रॉस जॉइन ऑपरेशन की तरह है जहां यह क्रॉस उत्पाद लेता है।
उदाहरण के लिए यदि हमारे पास है

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

निम्नलिखित सेट प्राप्त करने के लिए कई का उपयोग किया जा सकता है

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

ध्यान दें कि यहां हम सेट ए और सेट बी के तत्वों से बने सभी संभावित संयोजनों को ले सकते हैं।

यहाँ एक LINQ उदाहरण है जिसे आप आज़मा सकते हैं

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

मिश्रण में समतल संरचना में निम्नलिखित तत्व होंगे जैसे

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

4
मुझे पता है कि यह पुराना है, लेकिन मैं आपको इसके लिए धन्यवाद देना चाहता हूं, इसने मुझे बहुत बचाया! :) उन कोड के संदर्भ में भी उपयोगी हो सकता है: stackoverflow.com/questions/3479980/… चीयर्स!
user3439065

4
SelectMany का उपयोग उस तरह नहीं किया जाना चाहिए। इसमें सिर्फ एक फ़ंक्शन भी लेने का विकल्प है।
बार्लॉप

2
मुझे पता नहीं है कि यह कहना सही है कि यह कैसा SelectMany है । बल्कि, यह एक ऐसा तरीका है SelectManyजिसका उपयोग किया जा सकता है, लेकिन वास्तव में इसका उपयोग करने का सामान्य तरीका नहीं है।
डेव कज़िन्यू

1
मेरे लिए यह सबसे सरल उत्तर था।
चैम एलियाह

यह अच्छा होगा यदि आप WhereSelectMany के बाद भी स्थिति प्रदर्शित करते हैं
नितिन केटी

126

यहां छवि विवरण दर्ज करें

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

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}
  1. उपनाम
  2. अल्बा
  3. कोस्टा
  4. विला
  5. बस्कट्स

...


9
महान उदाहरण डेटा
15

1
क्या आप इस उत्तर को पूरा करने के लिए एक उदाहरण जोड़ सकते हैं :)
हैरी

73

SelectMany()आपको एक बहुआयामी अनुक्रम को इस तरह से ध्वस्त करने की अनुमति देता है जिसमें अन्यथा एक दूसरे Select()या लूप की आवश्यकता होती है ।

इस ब्लॉग पोस्ट में अधिक जानकारी ।


लेकिन पहले एक वापसी Enumerables प्रकार के बच्चों का दूसरा उदाहरण रिटर्न प्रकार माता-पिता का? वास्तव में मैं थोड़ा भ्रमित हूं, क्या आप इसे थोड़ा और खोलेंगे?
तारिक

अन्य तरीके से, वास्तव में। दूसरा पूरी तरह से enumerables के पदानुक्रम को समतल कर देगा, ताकि आपको बच्चे वापस मिल जाएं। मेरे द्वारा जोड़े गए लिंक पर लेख को देखें, देखें कि क्या मदद करता है।
माइकल पेट्रोत्ता

पहले वाला कानूनी नहीं लगता है। मुझे लगता है कि पोस्टर खुद उलझ गया। दूसरा कोई माता-पिता का पता नहीं लगाएगा।
5

धन्यवाद, वास्तव में हाँ हाँ उदाहरण थो थो भ्रमित करने वाले थे :) लेकिन फिर से मेरी मदद करने की कोशिश करने के लिए धन्यवाद।
तारिक

37

कई ओवरलोड हैं SelectMany। उनमें से एक आपको पदानुक्रम का पता लगाने के दौरान माता-पिता और बच्चों के बीच किसी भी संबंध का पता लगाने की अनुमति देता है।

उदाहरण : मान लीजिए आप निम्नलिखित संरचना है: League -> Teams -> Player

आप आसानी से खिलाड़ियों का एक फ्लैट संग्रह वापस कर सकते हैं। हालाँकि आप उस टीम का कोई भी संदर्भ खो सकते हैं जिसका खिलाड़ी हिस्सा है।

सौभाग्य से इस तरह के उद्देश्य के लिए एक अधिभार है:

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

पिछला उदाहरण डैन के आईके ब्लॉग से लिया गया है । मैं दृढ़ता से आपको इसे देखने की सलाह देता हूं।


19

मैं SelectManyएक शॉर्टकट की तरह काम करना समझता हूं ।

तो तुम कर सकते हो:

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

प्रदान किया गया उदाहरण काम करता है, लेकिन SelectMany एक जॉइन की तरह बिल्कुल काम नहीं करता है। एक जुड़ाव मूल तालिका के किसी भी क्षेत्र को जोड़ने और शामिल तालिका के किसी भी क्षेत्र को "उपयोग" करने की अनुमति देता है। लेकिन यहां आपको मूल तालिका से जुड़ी सूची की एक वस्तु निर्दिष्ट करनी होगी। उदाहरण के लिए, .SelectMany(c => new {c.CompanyName, c.Orders.ShippedDate});काम नहीं करेगा। SelectMany बल्कि सूचियों की सूची को समतल कर रहा है - और आप परिणाम के लिए निहित सूचियों में से किसी भी (लेकिन एक समय में केवल एक) को चुन सकते हैं। तुलना के लिए: इनर में शामिल हों
मैट

13

चयन एक सरल एक-से-एक प्रक्षेपण है जो स्रोत तत्व से परिणाम तत्व तक है। चयन करें- कई का उपयोग तब किया जाता है जब एक क्वेरी अभिव्यक्ति में कई खंड होते हैं: मूल अनुक्रम में प्रत्येक तत्व का उपयोग एक नया अनुक्रम उत्पन्न करने के लिए किया जाता है।


7

कुछ SelectMany आवश्यक नहीं हो सकता है। नीचे 2 प्रश्न समान परिणाम देते हैं।

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

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

1 से कई संबंधों के लिए,

  1. यदि "1" से प्रारंभ करें, SelectMany की आवश्यकता है, तो यह कई समतल करता है।
  2. यदि "कई" से प्रारंभ करें, SelectMany की आवश्यकता नहीं है। ( अभी भी "1" से फ़िल्टर करने में सक्षम हैं , यह भी मानक जॉइन क्वेरी के नीचे से सरल है)

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

4

बहुत अधिक तकनीकी के बिना - कई संगठनों के साथ डेटाबेस, प्रत्येक कई उपयोगकर्ताओं के साथ: -

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

दोनों चयनित संगठन के लिए समान ApplicationUser सूची लौटाते हैं ।

संगठन से उपयोगकर्ताओं के लिए पहला "प्रोजेक्ट", दूसरा उपयोगकर्ता सीधे तालिका पर सवाल उठाता है।


3

यह और अधिक स्पष्ट है जब क्वेरी एक स्ट्रिंग (चार का एक सरणी) लौटाती है:

उदाहरण के लिए यदि सूची में 'फल' में 'सेब' है

'चयन' स्ट्रिंग लौटाता है:

Fruits.Select(s=>s) 

[0]: "apple"

'SelectMany' स्ट्रिंग को समतल करता है:

Fruits.SelectMany(s=>s)

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

2

बस एक वैकल्पिक दृश्य के लिए जो कुछ कार्यात्मक प्रोग्रामर को वहाँ से बाहर निकलने में मदद कर सकता है:

  • Select है map
  • SelectManyहै bind(या flatMapआपके स्काला / कोटलिन लोगों के लिए)

2

इस उदाहरण पर विचार करें:

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

इसलिए जैसा कि आप देखते हैं कि "I" या "like" जैसे डुप्लिकेट मान क्वेरी 2 से हटा दिए गए हैं क्योंकि "SelectMany" कई अनुक्रमों में समतल और प्रोजेक्ट करता है। लेकिन query1 स्ट्रिंग सरणियों का अनुक्रम देता है। और चूंकि क्वेरी 1 (पहले और दूसरे तत्व) में दो अलग-अलग सरणियां हैं, कुछ भी नहीं हटाया जाएगा।


शायद बेहतर करने के लिए अब अंत और राज्य में .Distinct () शामिल हैं यह आउटपुट "मैं" "की तरह" "क्या" "मैं" "की तरह" "मैं" "की तरह" क्या "" आप "" की तरह ""
प्रोफेसर

1

उप सरणी ऑब्जेक्ट्स डेटा को संचित करने के लिए SelectMany + Select का उपयोग कैसे किया जा सकता है, इसका एक और उदाहरण।

मान लें कि हमारे पास फ़ोन वाले उपयोगकर्ता हैं:

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

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

अब हमें सभी उपयोगकर्ताओं के सभी फोन के बेसपार्ट्स का चयन करने की आवश्यकता है:

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

आपके हिसाब से कौन बेहतर है? तुम्हारा याusersArray.SelectMany(ua => ua.Phones.Select(p => p.BasePart))
माइकल बेस्ट

-1

परीक्षण के लिए प्रारंभिक छोटे संग्रह के साथ एक कोड उदाहरण यहां दिया गया है:

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

SelectManyएक नीचे विधि दस्तक देता है IEnumerable<IEnumerable<T>>एक में IEnumerable<T>, साम्यवाद की तरह, हर तत्व एक ही तरीके से व्यवहार किया जाता है (एक मूर्ख पुरुष एक genious एक का एक ही अधिकार है)।

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

-5

मुझे लगता है कि यह समझने का सबसे अच्छा तरीका है।

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

गुणन तालिका उदाहरण।


4
केवल अगर "सर्वश्रेष्ठ" का अर्थ नाटकीय रूप से बदल गया है।
वाहिद अमीरी

2
तो यह सबसे अच्छा तरीका है यू लगता है ?? फिर सोचने का कठिन तरीका क्या है ??
सैयद अली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.