LINQ বেনামে প্রকারের সাথে পৃথক নির্বাচন করুন


150

সুতরাং আমি অবজেক্টের একটি সংগ্রহ আছে। সঠিক ধরণটি গুরুত্বপূর্ণ নয়। এটি থেকে আমি এক বিশেষ বৈশিষ্ট্যের এক জোড়া সমস্ত অনন্য জোড়া বের করতে চাই:

myObjectCollection.Select(item=>new
                                {
                                     Alpha = item.propOne,
                                     Bravo = item.propTwo
                                }
                 ).Distinct();

সুতরাং আমার প্রশ্নটি হ'ল: এই ক্ষেত্রে কী বিচ্ছিন্ন হবে ডিফল্ট অবজেক্ট সমান (যা আমার কাছে অকেজো হবে, যেহেতু প্রতিটি বস্তু নতুন) বা এটি আলাদা সমান করতে বলা যেতে পারে (এই ক্ষেত্রে, আলফা এবং ব্র্যাভোর সমান মানগুলি => সমান দৃষ্টান্ত)? ফলাফলটি অর্জন করার কোনও উপায় আছে, যদি এটি এটি না করে?


এই লিনকিউ-টু-অবজেক্টস বা লিনকিউ-টু-এসকিউএল? যদি কেবল অবজেক্ট হয় তবে আপনি সম্ভবত ভাগ্যের বাইরে রয়েছেন। যাইহোক, যদি L2S হয়, তবে এটি কার্যকর হতে পারে, কারণ DISTINCT এসকিউএল স্টেটমেন্টের মধ্য দিয়ে দেওয়া হবে।
জেমস কারান

উত্তর:


188

স্কট অ্যালেনের দুর্দান্ত পোস্টটি এখানে পড়ুন:

এবং সকলের জন্য সমতা ... নামবিহীন প্রকারগুলি

সংক্ষিপ্ত উত্তর (এবং আমি উদ্ধৃতি):

বেনামি ধরণের জন্য সি # সংকলক সমান ও গেটহ্যাশকোডকে ওভাররাইড করে। দুটি ওভাররাইড হওয়া পদ্ধতিগুলির বাস্তবায়নের জন্য কোনও সামগ্রীর হ্যাশ কোড গণনা করতে এবং সমতার জন্য পরীক্ষার জন্য ধরণের সমস্ত পাবলিক বৈশিষ্ট্য ব্যবহার করা হয়। যদি একই বেনামে টাইপের দুটি অবজেক্টের বৈশিষ্ট্যগুলির জন্য একই মান থাকে - অবজেক্ট সমান।

সুতরাং বেনামি ধরণের প্রত্যাবর্তনকারী ক্যোয়ারিতে ডিস্ট্রিন্ট () পদ্ধতিটি ব্যবহার করা সম্পূর্ণ নিরাপদ।


2
এটি কেবল সত্য, আমি মনে করি, সম্পত্তিগুলি যদি নিজেরাই মান ধরণের হয় বা মান সমতা প্রয়োগ করে - তবে আমার উত্তর দেখুন।
tvanfosson

হ্যাঁ, যেহেতু এটি প্রতিটি সম্পত্তিতে গেটহ্যাশকোড ব্যবহার করে তবে এটি কেবল তখনই কাজ করবে যদি প্রতিটি সম্পত্তির নিজস্ব অনন্য বাস্তবায়ন থাকে। আমি মনে করি বেশিরভাগ ব্যবহারের ক্ষেত্রে কেবল বৈশিষ্ট্য হিসাবে সাধারণ প্রকার জড়িত তাই এটি সাধারণত নিরাপদ।
ম্যাট হ্যামিল্টন

4
এটি বোধগম্য হয় যে বেনামে দুটি ধরণের সাম্যতা সদস্যদের সাম্যের উপর নির্ভর করে, যা আমার পক্ষে ঠিক আছে, যেহেতু সদস্যদের কোথাও সংজ্ঞায়িত করা হয়েছে যে আমি যদি পেতে পারি তবে আমি সাম্যকে ওভাররাইড করতে পারি। আমি শুধু সমান ওভাররাইড করার জন্য এটির জন্য কোনও শ্রেণি তৈরি করতে চাইনি।
জিডব্লু্ল্লোসা

3
ভিসির কাছে সি # তে "কী" সিনট্যাক্সটি প্রবর্তন করার জন্য এমএসের কাছে আবেদন করা উপযুক্ত হতে পারে (যেখানে আপনি 'প্রাথমিক কী' হিসাবে একটি বেনাম প্রকারের নির্দিষ্ট বৈশিষ্ট্য নির্দিষ্ট করতে পারেন - আমার সাথে সংযুক্ত ব্লগ পোস্টটি দেখুন)।
ম্যাট হ্যামিল্টন

1
খুব আকর্ষণীয় নিবন্ধ। ধন্যবাদ!
আলেকজান্ডার প্রোকোফিয়েভ

14
public class DelegateComparer<T> : IEqualityComparer<T>
{
    private Func<T, T, bool> _equals;
    private Func<T, int> _hashCode;
    public DelegateComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
    {
        _equals= equals;
        _hashCode = hashCode;
    }
    public bool Equals(T x, T y)
    {
        return _equals(x, y);
    }

    public int GetHashCode(T obj)
    {
        if(_hashCode!=null)
            return _hashCode(obj);
        return obj.GetHashCode();
    }       
}

public static class Extensions
{
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items, 
        Func<T, T, bool> equals, Func<T,int> hashCode)
    {
        return items.Distinct(new DelegateComparer<T>(equals, hashCode));    
    }
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
        Func<T, T, bool> equals)
    {
        return items.Distinct(new DelegateComparer<T>(equals,null));
    }
}

var uniqueItems=students.Select(s=> new {FirstName=s.FirstName, LastName=s.LastName})
            .Distinct((a,b) => a.FirstName==b.FirstName, c => c.FirstName.GetHashCode()).ToList();

গণ্ডগোল করা ফর্ম্যাটিংয়ের জন্য আগে দুঃখিত


এই এক্সটেনশানগুলি টাইপ objectএবং পরিচালনা করতে পারে না object। যদি উভয়ই objectহয় তবে stringএটির সদৃশ সারিগুলি ফেরত পাঠান। FirstNameটাইপফুলটি চেষ্টা করে দেখুন এবং সেখানে একইটি objectবরাদ্দ করুন string
কলমেলএএনএন

এটি টাইপযুক্ত সামগ্রীর জন্য দুর্দান্ত উত্তর তবে বেনামি ধরণের প্রয়োজন নেই।
ক্রোকুসেক

5

আকর্ষণীয় যে এটি সি # তে কাজ করে তবে ভিবিতে নয়

26 টি চিঠি ফেরত দেয়:

var MyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
MyBet.ToCharArray()
.Select(x => new {lower = x.ToString().ToLower(), upper = x.ToString().ToUpper()})
.Distinct()
.Dump();

৫২ ...

Dim MyBet = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
MyBet.ToCharArray() _
.Select(Function(x) New With {.lower = x.ToString.ToLower(), .upper = x.ToString.ToUpper()}) _
.Distinct() _
.Dump()

11
আপনি যদি Keyবেনামে কীওয়ার্ডটি যুক্ত করেন তবে .Distinct()উদ্দেশ্য হিসাবে কাজ করবে (যেমন New With { Key .lower = x.ToString.ToLower(), Key .upper = x.ToString.ToUpper()})।
সি

3
Cory ঠিক আছে। সি শার্প কোডের সঠিক অনুবাদ new {A = b}হয় New {Key .A = b}। বেনামে থাকা ভিবি ক্লাসে অ-কী বৈশিষ্ট্যগুলি পারস্পরিক পরিবর্তনযোগ্য, এজন্য এগুলি রেফারেন্সের সাথে তুলনা করা হয়। সি # তে, বেনাম শ্রেণীর সমস্ত সম্পত্তি অপরিবর্তনীয়।
হেইনজি

4

আমি কিছুটা পরীক্ষা করে দেখেছি যে বৈশিষ্ট্যগুলি যদি মান ধরণের হয় তবে এটি ঠিক আছে বলে মনে হচ্ছে। যদি সেগুলি মান ধরণের না হয় তবে টাইপটি এটির কাজ করার জন্য এটির নিজস্ব সমান এবং গেটহ্যাশকোড বাস্তবায়ন সরবরাহ করে। স্ট্রিংস, আমি ভাবব, কাজ করবে।


2

আপনি নিজের ডিস্টিন্ট এক্সটেনশন পদ্ধতি তৈরি করতে পারেন যা ল্যাম্বডা এক্সপ্রেশন লাগে। এখানে একটি উদাহরণ

আইকোয়ালিটি কম্পিউটারের ইন্টারফেস থেকে প্রাপ্ত একটি শ্রেণি তৈরি করুন

public class DelegateComparer<T> : IEqualityComparer<T>
{
    private Func<T, T, bool> _equals;
    private Func<T, int> _hashCode;
    public DelegateComparer(Func<T, T, bool> equals, Func<T, int> hashCode)
    {
        _equals= equals;
        _hashCode = hashCode;
    }
    public bool Equals(T x, T y)
    {
        return _equals(x, y);
    }

    public int GetHashCode(T obj)
    {
        if(_hashCode!=null)
            return _hashCode(obj);
        return obj.GetHashCode();
    }       
}

তারপরে আপনার বিচ্ছিন্ন এক্সটেনশন পদ্ধতিটি তৈরি করুন

public static class Extensions
{
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items, 
        Func<T, T, bool> equals, Func<T,int> hashCode)
    {
        return items.Distinct(new DelegateComparer<T>(equals, hashCode));    
    }
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items,
        Func<T, T, bool> equals)
    {
        return items.Distinct(new DelegateComparer<T>(equals,null));
    }
}

এবং আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন স্বতন্ত্র আইটেমগুলি সন্ধান করুন

var uniqueItems=students.Select(s=> new {FirstName=s.FirstName, LastName=s.LastName})
            .Distinct((a,b) => a.FirstName==b.FirstName, c => c.FirstName.GetHashCode()).ToList();

এই এক্সটেনশানগুলি টাইপ objectএবং পরিচালনা করতে পারে না object। যদি উভয়ই objectহয় তবে stringএটির সদৃশ সারিগুলি ফেরত পাঠান। FirstNameটাইপফুলটি চেষ্টা করে দেখুন এবং সেখানে একইটি objectবরাদ্দ করুন string
কলমেলএএনএন

0

যদি Alphaএবং Bravoউভয়ই একটি সাধারণ শ্রেণীর উত্তরাধিকারী হয় তবে আপনি বাস্তবায়নের মাধ্যমে প্যারেন্ট ক্লাসে সমতা চেকটি নির্দেশ করতে সক্ষম হবেনIEquatable<T>

উদাহরণ স্বরূপ:

public class CommonClass : IEquatable<CommonClass>
{
    // needed for Distinct()
    public override int GetHashCode() 
    {
        return base.GetHashCode();
    }

    public bool Equals(CommonClass other)
    {
        if (other == null) return false;
        return [equality test];
    }
}

সুতরাং আপনি যদি আপনার বেনামে ধরণের শ্রেণীর বৈশিষ্ট্য হিসাবে ব্যবহার করেন যা আইক্যাটেবল <টি> প্রয়োগ করে, ডিফল্ট আচরণের পরিবর্তে সমানকে বলা হয় (প্রতিচ্ছবি দ্বারা সমস্ত পাবলিক বৈশিষ্ট্যের চেক?)
ডি_গুইদি

0

আরে সেখানে আমি একই সমস্যা পেয়েছি এবং আমি একটি সমাধান খুঁজে পেয়েছি। আপনাকে আইক্যায়েটেবল ইন্টারফেস প্রয়োগ করতে হবে বা কেবল (সমতুল্য এবং গেটহ্যাশকোড) পদ্ধতিগুলি ওভাররাইড করতে হবে। তবে এটি কৌশল নয়, কৌশলটি গেটহ্যাশকোড পদ্ধতিতে আসছে। আপনার শ্রেণীর অবজেক্টের হ্যাশ কোডটি আপনাকে ফিরিয়ে দেওয়া উচিত নয় তবে আপনি যে সম্পত্তির তুলনা করতে চান তার হ্যাশটি আপনাকে ফিরিয়ে দেওয়া উচিত।

public override bool Equals(object obj)
    {
        Person p = obj as Person;
        if ( obj == null )
            return false;
        if ( object.ReferenceEquals( p , this ) )
            return true;
        if ( p.Age == this.Age && p.Name == this.Name && p.IsEgyptian == this.IsEgyptian )
            return true;
        return false;
        //return base.Equals( obj );
    }
    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }

আপনি দেখতে পান যে আমি একটি শ্রেণি পেয়েছি যার নাম ব্যক্তি পেয়েছিল 3 টি সম্পত্তি (নাম, বয়স, ইসিগাইপটিয়ান "কারণ আমি") গেটহ্যাশকোডে আমি ব্যক্তিগত সম্পত্তি হিসাবে নয় নামের সম্পত্তিটির হ্যাশ ফিরিয়ে দিয়েছি।

এটি ব্যবহার করে দেখুন এবং এটি আইএসএ কাজ করবে। ধন্যবাদ মোদাদর সাদিক


1
গেটহ্যাশকোডের একই ক্ষেত্র এবং বৈশিষ্ট্যগুলি ব্যবহার করা উচিত যা সাম্যের জন্য তুলনায় ব্যবহৃত হয়, কেবল তার মধ্যে একটি নয়। অর্থাত্public override int GetHashCode() { return this.Name.GetHashCode() ^ this.Age.GetHashCode() ^ this.IsEgyptian.GetHashCode(); }
এসডিতে জেজি

একটি ভাল হ্যাশ অ্যালগরিদম উত্পাদন সম্পর্কিত তথ্যের জন্য: স্ট্যাকওভারফ্লো.com
এসডিতে জে জি

0

এটি VB.NET এ কাজ করার জন্য, আপনাকে Keyবেনামে টাইপের প্রতিটি সম্পত্তির আগে কীওয়ার্ডটি নির্দিষ্ট করতে হবে যেমন ঠিক:

myObjectCollection.Select(Function(item) New With
{
    Key .Alpha = item.propOne,
    Key .Bravo = item.propTwo
}).Distinct()

আমি এটির সাথে লড়াই করে যাচ্ছিলাম, আমি ভেবেছিলাম ভিবি.এনইটি এই ধরণের বৈশিষ্ট্য সমর্থন করে না, তবে বাস্তবে তা করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.