linq क्वेरी ऑब्जेक्ट की सूची से अलग फ़ील्ड मान वापस करने के लिए


88
class obj
{
    int typeId; //10 types  0-9 
    string uniqueString; //this is unique
}

मान लें कि obj के 100 तत्वों के साथ सूची है, लेकिन केवल 10 अद्वितीय टाइपिड्स।
क्या यह संभव है कि LINQ क्वेरी को 10 अद्वितीय इन्ट्स को objs की सूची से लौटा दें?


यह सवाल इतना आसान है और इनाम के लायक नहीं है।
चिंतक

जवाबों:


155
objList.Select(o=>o.typeId).Distinct()

2
दूसरा रूप डिस्टिंक्ट के अधिभार का उपयोग करने के लिए प्रतीत होता है जो अब तक मौजूद नहीं है क्योंकि मैं जागरूक हूं।
जॉन स्कीट

ओह, दूसरे को हटा दिया, धन्यवाद @Jon Skeet, जिसे IEqualityComparer
Arsen Mkrtchyan

3
जैसा कि जॉन स्कीट ने उल्लेख किया है, यह केवल चयन में निर्दिष्ट गुणों को लौटाएगा।
Peet vd Westhuizen

58

यह मानते हुए कि आप पूरी वस्तु चाहते हैं, लेकिन केवल विशिष्टता से निपटना चाहते हैं typeID, इस आसान को बनाने के लिए LINQ में कुछ भी नहीं बनाया गया है। (यदि आप केवलtypeID मान चाहते हैं, तो यह आसान है - उस प्रोजेक्ट पर जाएं Selectऔर फिर सामान्य Distinctकॉल का उपयोग करें।)

में MoreLINQ हमारे पास DistinctByऑपरेटर जो आप इस्तेमाल कर सकते हैं:

var distinct = list.DistinctBy(x => x.typeID);

यह केवल LINQ ऑब्जेक्ट्स के लिए काम करता है।

आप ग्रुपिंग या लुकअप का उपयोग कर सकते हैं, यह कुछ हद तक कष्टप्रद और अक्षम है:

var distinct = list.GroupBy(x => x.typeID, (key, group) => group.First());


1
@ शील: नहीं, मैं MoreLINQ में डिस्टिंक्टबी के बारे में लिख रहा था। Microsoft.Ajax.Utilities से कोई लेना देना नहीं है।
जॉन स्कीट

अब मैं देख सकता हूं कि LINQ में डिस्टिक्ट का एक अधिभार है जो एक IEqualityComparer को पैरामीटर के रूप में लेता है और IEqualityComparer में विधियों के कार्यान्वयन के आधार पर अलग-अलग ऑब्जेक्ट्स की एक सूची लौटाता है
Dipendu पॉल

1
@DipenduPaul: हां, लेकिन इसका मतलब अभी भी किसी दिए गए संपत्ति के लिए समानता समानता बनाना है, जो कष्टप्रद है और इसे पढ़ने के लिए कठिन बना देता है। यदि आप MoreLINQ निर्भरता ले सकते हैं, मुझे लगता है कि क्लीनर है।
जॉन स्कीट

22

यदि आप केवल शुद्ध Linq उपयोगकर्ता चाहते हैं, तो आप groupby का उपयोग कर सकते हैं:

List<obj> distinct =
  objs.GroupBy(car => car.typeID).Select(g => g.First()).ToList();

यदि आप चाहते हैं कि एक विधि सभी अनुप्रयोग में उपयोग की जाए, तो MoreLinq क्या करता है:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (!seenKeys.Contains(keySelector(element)))
        {
            seenKeys.Add(keySelector(element));
            yield return element;
        }
    }
}

सिर्फ आईडी प्रॉपर्टी का उपयोग करके विभिन्न मूल्यों को खोजने के लिए इस पद्धति का उपयोग करके, आप इसका उपयोग कर सकते हैं:

var query = objs.DistinctBy(p => p.TypeId);

आप कई गुणों का उपयोग कर सकते हैं:

var query = objs.DistinctBy(p => new { p.TypeId, p.Name });

कई गुण भाग के लिए धन्यवाद !
नाए

7

ज़रूर, उपयोग करें Enumerable.Distinct

obj(जैसे foo) के संग्रह को देखते हुए , आप ऐसा कुछ करेंगे:

var distinctTypeIDs = foo.Select(x => x.typeID).Distinct();

5

मुझे लगता है कि यह आपकी तलाश है:

    var objs= (from c in List_Objects 
orderby c.TypeID  select c).GroupBy(g=>g.TypeID).Select(x=>x.FirstOrDefault());      

LINQ के साथ इस रिटर्निंग अ डिस्टिक्ट IQueryable के समान है ?


.Firstठीक है, क्योंकि आपके पास समूह नहीं होगा यदि उसमें कुछ नहीं था।
18

1
आप GroupByइसे सरल बनाने के लिए एक वैकल्पिक अधिभार का उपयोग कर सकते हैं - एक उदाहरण के लिए मेरा उत्तर देखें।
जॉन स्कीट

3

यदि आप Linq का उपयोग करना चाहते हैं, तो आप Equals और GetHashCode विधियों को ओवरराइड कर सकते हैं ।

उत्पाद वर्ग:

public class Product
{
    public string ProductName { get; set; }
    public int Id { get; set; }


    public override bool Equals(object obj)
    {
        if (!(obj is Product))
        {
            return false;
        }

        var other = (Product)obj;
        return Id == other.Id;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

मुख्य विधि:

static void Main(string[] args)
    {

        var products = new List<Product>
        {
            new Product{ ProductName="Product 1",Id = 1},
            new Product{ ProductName="Product 2",Id = 2},
            new Product{ ProductName="Product 4",Id = 5},
            new Product{ ProductName="Product 3",Id = 3},
            new Product{ ProductName="Product 4",Id = 4},
            new Product{ ProductName="Product 6",Id = 4},
            new Product{ ProductName="Product 6",Id = 4},
        };

        var itemsDistinctByProductName = products.Distinct().ToList();

        foreach (var product in itemsDistinctByProductName)
        {
            Console.WriteLine($"Product Id : {product.Id} ProductName : {product.ProductName} ");
        }

        Console.ReadKey();
    }

1

मैं एक विशेष डेटा को ड्रॉपडाउन से बांधना चाहता था और यह अलग होना चाहिए। मैंने निम्नलिखित कार्य किया:

List<ClassDetails> classDetails;
List<string> classDetailsData = classDetails.Select(dt => dt.Data).Distinct.ToList();
ddlData.DataSource = classDetailsData;
ddlData.Databind();

देखें कि क्या यह मदद करता है

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