Linq में सूची से कई फ़ील्ड चुनें


128

ASP.NET C # में मेरे पास एक संरचना है:

public struct Data
{
    public int item1;
    public int item2;
    public int category_id;
    public string category_name;
}

और मेरे पास उन लोगों की सूची है। मैं चयन करना चाहते हैं category_idऔर category_nameसंभव है कि दौड़ने DISTINCTऔर अंत में एक ORDERBYपर category_name

यहाँ अब मेरे पास क्या है:

List<Data> listObject = getData();
string[] catNames = listObject
                    .Select(i=> i.category_name)
                    .Distinct()
                    .OrderByDescending(s => s)
                    .ToArray();

यह स्पष्ट रूप से सिर्फ श्रेणी का नाम है। मेरा प्रश्न यह है कि मुझे कई फ़ील्ड कैसे मिलेंगे, और मैं इसे किस डेटा संरचना में संग्रहीत करूँगा (नहीं)string[] ) ?

संपादित करें

पत्थरों की सूची का उपयोग करना पत्थर में सेट नहीं है। यदि चयनों को आसान बनाने के लिए मेरी बैकिंग डेटा संरचना को बदलना उचित होगा (मैं इनमें से बहुत कुछ लिखूंगा) तो मैं ख़ुशी से सिफारिशें लूंगा।


10
हालांकि यह LINQ पक्ष से असंबंधित है, मैं आपको दृढ़ता से सलाह देना चाहूंगा कि आप उत्परिवर्तित संरचनाओं या सार्वजनिक क्षेत्रों का उपयोग न करें। व्यक्तिगत रूप से मैं शायद ही कभी पहले स्थान पर संरचनाएं बनाता हूं, लेकिन उत्परिवर्तित संरचनाएं केवल परेशानी के लिए पूछ रही हैं।
जॉन स्कीट

@Jon Skeet धन्यवाद। मैं इसे निजी सदस्यों के साथ एक नियमित वर्ग में परिवर्तित करूँगा।
चेत

1
@Midhat: म्यूटेबल स्ट्रक्चर्स सभी प्रकार की समस्याओं का कारण बनते हैं, क्योंकि वे लोगों से वैसा व्यवहार नहीं करते हैं, जैसा वे उनसे करते हैं। और सार्वजनिक क्षेत्र इनकैप्सुलेशन का पूर्ण अभाव देते हैं।
जॉन स्कीट

@ जोंन स्कीट क्या आप परिवर्तनशील संरचनाओं के नुकसान के साथ अधिक विशिष्ट हो सकते हैं, या मुझे पढ़ने के लिए इंगित कर सकते हैं।
Midhat

2
@Midhat: शुरुआती बिंदु के लिए stackoverflow.com/questions/441309/why-are-mutable-structs-evil पर एक नज़र डालें ।
जॉन स्कीट

जवाबों:


228

अनाम प्रकार आपको डेटा संरचनाओं में मनमाने ढंग से फ़ील्ड चुनने की अनुमति देते हैं जो आपके कोड में बाद में दृढ़ता से टाइप किए जाते हैं:

var cats = listObject
    .Select(i => new { i.category_id, i.category_name })
    .Distinct()
    .OrderByDescending(i => i.category_name)
    .ToArray();

चूंकि आपको (जाहिरा तौर पर) इसे बाद में उपयोग करने के लिए स्टोर करने की आवश्यकता है, आप GroupBy ऑपरेटर का उपयोग कर सकते हैं:

Data[] cats = listObject
    .GroupBy(i => new { i.category_id, i.category_name })
    .OrderByDescending(g => g.Key.category_name)
    .Select(g => g.First())
    .ToArray();

मैं 1 कॉलम पर विशिष्ट का उपयोग करना चाहता हूं और कई कॉलम पुनर्प्राप्त करना चाहता हूं। मैं यह कैसे कर सकता हूं?
किशन गज्जर

1
मैंने कभी Selectनए प्रकार में नहीं सोचा । मेरे मामले में मैंने एक नए में चयन किया KeyValuePair
cjbarth

26
var selectedCategories =
    from value in
        (from data in listObject
        orderby data.category_name descending
        select new { ID = data.category_id, Name = data.category_name })
    group value by value.Name into g
    select g.First();

foreach (var category in selectedCategories) Console.WriteLine(category);

संपादित करें : इसे और अधिक LINQ- आंख बनाया!


Haha, धन्यवाद, ठीक है, मैं मदद की सराहना करते हैं। जाहिर तौर पर यह दुनिया का सबसे कठिन सवाल नहीं था।
चेत

@IRBMe क्षमा करें, छोटा सा प्रश्न। वास्तव में 'मूल्य' क्या है?
फर्नांडो एस। क्रोज

23

आप एक अनाम प्रकार का उपयोग कर सकते हैं:

.Select(i => new { i.name, i.category_name })

संकलक के साथ एक वर्ग के लिए कोड उत्पन्न होगा nameऔर category_nameगुण और रिटर्न उस वर्ग के उदाहरण। आप संपत्ति के नामों को मैन्युअल रूप से निर्दिष्ट कर सकते हैं:

i => new { Id = i.category_id, Name = i.category_name }

आपके पास गुणों की मनमानी संख्या हो सकती है।


6

आप कई क्षेत्रों का चयन कर सकते हैं linq का उपयोग करके चुनें जैसा कि ऊपर दिखाया गया है विभिन्न उदाहरणों में यह एक अनाम प्रकार के रूप में वापस आ जाएगा। यदि आप इस गुमनाम प्रकार से बचना चाहते हैं तो यहाँ सरल चाल है।

var items = listObject.Select(f => new List<int>() { f.Item1, f.Item2 }).SelectMany(item => item).Distinct();

मुझे लगता है कि यह आपकी समस्या को हल करता है


5

यह किस अनाम प्रकार के लिए कार्य है बहुत अच्छी तरह से अनुकूल हैं। आप संकलक द्वारा उपयोग किए गए कंपाइलर द्वारा बनाई गई एक प्रकार की वस्तुओं को वापस कर सकते हैं।

वाक्य रचना इस प्रकार है:

new { Property1 = value1, Property2 = value2, ... }

अपने मामले के लिए, निम्न की तरह कुछ प्रयास करें:

var listObject = getData();
var catNames = listObject.Select(i =>
    new { CatName = i.category_name, Item1 = i.item1, Item2 = i.item2 })
    .Distinct().OrderByDescending(s => s).ToArray();

4
var result = listObject.Select( i => new{ i.category_name, i.category_id } )

यह अनाम प्रकारों का उपयोग करता है, इसलिए आपको var कीवर्ड चाहिए, क्योंकि परिणामी प्रकार की अभिव्यक्ति पहले से ज्ञात नहीं है।



3

आप इसे KeyValuePair बना सकते हैं, इसलिए यह ए वापस कर देगा "IEnumerable<KeyValuePair<string, string>>"

तो, यह इस तरह होगा:

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name )).Distinct();

यह एक लाभ के बिना अनावश्यक जटिलता कहते हैं
Matze

2
public class Student
{
    public string Name { set; get; }
    public int ID { set; get; }
}

class Program
{
  static void Main(string[] args)
    {
        Student[] students =
        {
        new Student { Name="zoyeb" , ID=1},
        new Student { Name="Siddiq" , ID=2},
        new Student { Name="sam" , ID=3},
        new Student { Name="james" , ID=4},
        new Student { Name="sonia" , ID=5}
        };

        var studentCollection = from s in students select new { s.ID , s.Name};

        foreach (var student in studentCollection)
        {
            Console.WriteLine(student.Name);
            Console.WriteLine(student.ID);
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.