দুটি তালিকার মধ্যে পার্থক্য


118

আমার কাছে কাস্টমসঅবজেক্টে ভরা দুটি জেনেরিক তালিকা রয়েছে।

আমাকে তৃতীয় তালিকায় সেই দুটি তালিকার মধ্যে (দ্বিতীয়টি আইটেম ছাড়া প্রথম যে আইটেমগুলি রয়েছে) এর মধ্যে পার্থক্যটি পুনরুদ্ধার করতে হবে।

আমি ভাবছিলাম ব্যবহার .Except()করা ভাল ধারণা ছিল তবে আমি কীভাবে এটি ব্যবহার করব তা দেখছি না ... সহায়তা!

c# 

উত্তর:


237

ব্যবহার Exceptকরা ঠিক যাওয়ার সঠিক উপায়। যদি আপনার ধরণটি ওভাররাইড হয় Equalsএবং GetHashCodeবা আপনি কেবলমাত্র রেফারেন্সের ধরণের সমতাতে আগ্রহী হন (উদাহরণস্বরূপ দুটি রেফারেন্স কেবল "সমান" তবে তারা সঠিক একই বস্তুর উল্লেখ করে) আপনি কেবল ব্যবহার করতে পারেন:

var list3 = list1.Except(list2).ToList();

যদি আপনাকে সাম্যতার একটি কাস্টম ধারণা প্রকাশ করতে হয়, যেমন আইডি দ্বারা, আপনাকে বাস্তবায়ন করতে হবে IEqualityComparer<T>। উদাহরণ স্বরূপ:

public class IdComparer : IEqualityComparer<CustomObject>
{
    public int GetHashCode(CustomObject co)
    {
        if (co == null)
        {
            return 0;
        }
        return co.Id.GetHashCode();
    }

    public bool Equals(CustomObject x1, CustomObject x2)
    {
        if (object.ReferenceEquals(x1, x2))
        {
            return true;
        }
        if (object.ReferenceEquals(x1, null) ||
            object.ReferenceEquals(x2, null))
        {
            return false;
        }
        return x1.Id == x2.Id;
    }
}

তারপরে ব্যবহার করুন:

var list3 = list1.Except(list2, new IdComparer()).ToList();

নোট করুন যে এটি কোনও সদৃশ উপাদান মুছে ফেলবে। সংরক্ষণের জন্য যদি আপনার ডুপ্লিকেটগুলির প্রয়োজন হয় তবে একটি সেট তৈরি করা list2এবং এর মতো কিছু ব্যবহার করা সম্ভবত সবচেয়ে সহজ হবে :

var list3 = list1.Where(x => !set2.Contains(x)).ToList();

18
ঠিক আলাদা আলাদাভাবে , আমি Exceptএটি সেট অপারেশন হিসাবে যুক্ত করব, তারপরে ফলাফলের তালিকার স্বতন্ত্র মান থাকবে, যেমন, {'A','A','B','C'}.Except({'B','C'}) প্রত্যাবর্তন{'A'}
— digEmAll

4
আমার কাছে এটি রয়েছে: A 'এ', 'এ', 'বি', 'সি'}। ({'বি', 'সি'}) ছাড়া 'এ' returns যা কাজ করে ... তবে B 'বি' , 'সি'}। ({'এ', 'বি', 'সি'})
— বাদে

2
দুটি সেটের সেট পার্থক্যটি প্রথম সেটের সদস্য হিসাবে সংজ্ঞায়িত করা হয় যা দ্বিতীয় সেটে উপস্থিত হয় না (এমএসের উদ্ধৃতি দিয়ে)। সুতরাং, {বি, সি}। ছাড়া ({এ, বি, সি x) কোনও কিছুই ফেরত দেওয়া উচিত নয় কারণ বি এবং সি উভয়ই দ্বিতীয় সেটে রয়েছে। কোনও বাগ নয়, ফাংশনের গাণিতিক সংজ্ঞাটি আরও বেশি।
— স্টিভ হিবার্ট

সুতরাং @ জোনস্কিট যদি আমি 2 টি বৈশিষ্ট্যের ভিত্তিতে দুটি তালিকার তুলনা করতে চাই তবে আমি এইভাবে তুলনামূলক লিখতে পারি এবং আইটেমগুলি সমান সঠিক নয় তা পেতে পারি?
— এহসান সাজ্জাদ

1
@ নেটমেজ: ওপি জানিয়েছে যে তারা "দ্বিতীয় আইটেম ছাড়া প্রথম যে আইটেমগুলি চায়" - এটি আমার কাছে একটি নির্দিষ্ট পার্থক্যের মতো মনে হয়। যদি প্রথম তালিকায় {5, 5, 5, 5, 1} এবং দ্বিতীয় তালিকায় {5} থাকে তবে কেবল 1 টি প্রথম তালিকায় তবে দ্বিতীয়টি নয়।
— জন স্কিটি

72

আপনি এরকম কিছু করতে পারেন:

var result = customlist.Where(p => !otherlist.Any(l => p.someproperty == l.someproperty));

এটি আমার এক ফর্চ লুপ সংরক্ষণ করেছে।
— এলিস 7

12
সেই "l.someproperty" এর মধ্যে একটিও "p.someproperty" হওয়া উচিত নয়?
— মনস দিলাভেরাকিস

6
এটি কাস্টমলিস্ট দিয়ে সরলীকৃত করা যেতে পারে W যেখানে (পি => অন্যান্য তালিকা। যে কোনও (l => পি.সোমপ্রোপার্টি! = L.someproperty));
— ধনুকা 777

@ ধনুকা 7 .7 এটি ভুল। Anyএকটি হওয়া উচিত Allযদি তোমরা যে ভালো এটা করতে চাই। এটি কারণ এই যে দ্বিতীয় তালিকায় প্রথম তালিকা থেকে আইটেমটি থাকতে পারে তবে এটি যদি প্রথমটি পরীক্ষিত না হয় তবে তা অবিলম্বে এটির জন্য সত্য হয়ে উঠবে p.someproperty != l.someproperty। উভয় তালিকায় বিদ্যমান আইটেমগুলির ফলশ্রুতিতে। লজ্জা 6 জন লোক যারা এটি upvated।
— মারফিব্রো

26

আমি জোর দেওয়া গুরুত্বপূর্ণ বলে মনে করি - পদ্ধতি ব্যতীত আপনি কেবল দ্বিতীয়টিতে আইটেম ছাড়াই প্রথমে থাকা আইটেমগুলি ফিরিয়ে আনবেন । এটি দ্বিতীয়টিতে সেই উপাদানগুলিকে ফেরত দেয় না যা প্রথমে প্রদর্শিত হয় না।

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list3 = list1.Except(list2).ToList(); //list3 contains only 1, 2

তবে আপনি যদি দুটি তালিকার মধ্যে সত্যিকারের পার্থক্য পেতে চান:

আইটেমগুলি যারা দ্বিতীয় একের আইটেম ছাড়াই প্রথম এবং আইটেমগুলি প্রথমটিতে থাকা আইটেমগুলি ছাড়াই।

আপনার দু'বার বাদে ব্যবহার করা দরকার:

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list3 = list1.Except(list2); //list3 contains only 1, 2
var list4 = list2.Except(list1); //list4 contains only 6, 7
var resultList = list3.Concat(list4).ToList(); //resultList contains 1, 2, 6, 7

অথবা আপনি ব্যবহার করতে পারেন SymmetricExceptWith HashSet পদ্ধতি। তবে এটি সেটে পরিবর্তন করে যার উপর ডাকা হয়:

var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };

var list1Set = list1.ToHashSet(); //.net framework 4.7.2 and .net core 2.0 and above otherwise new HashSet(list1)
list1Set.SymmetricExceptWith(list2);
var resultList = list1Set.ToList(); //resultList contains 1, 2, 6, 7

এটা সহায়ক। শুধু সচেতন থাকুন ওপি স্পষ্ট করে দিয়েছে যে তারা পুরো পার্থক্য চায় না: "আমাকে সেই দুটি তালিকার মধ্যে পার্থক্যটি পুনরুদ্ধার করতে হবে (যে আইটেমগুলি প্রথমটিতে আইটেম ছাড়াই প্রথম রয়েছে )"।
— আরএসএনএ

10
var third = first.Except(second);

(আপনি যদি অলস সংগ্রহগুলি উল্লেখ না করেন তবে আপনি ToList()পরেও কল করতে পারেন Except()))

Except()পদ্ধতি, ডিফল্ট comparer ব্যবহার মান তুলনা যদি মান তুলনা করা হচ্ছে বেস ধরনের তথ্য রয়েছে, যেমন int, string, decimalইত্যাদি

অন্যথায় তুলনাটি অবজেক্টের ঠিকানার মাধ্যমে তৈরি করা হবে যা সম্ভবত আপনি যা চান তা নয় ... সেক্ষেত্রে আপনার কাস্টম অবজেক্টগুলি বাস্তবায়ন করুন IComparable(বা একটি কাস্টম বাস্তবায়ন করুন IEqualityComparerএবং এটি Except()পদ্ধতিতে পাস করুন )।


3
var list3 = list1.Where(x => !list2.Any(z => z.Id == x.Id)).ToList();

দ্রষ্টব্য: list3এতে এমন দুটি আইটেম বা বস্তু থাকবে যা উভয় তালিকায় নেই। দ্রষ্টব্য: এটি ToList()নাtoList()


1

যেহেতু এক্সটেনশন পদ্ধতিটি দুটি আইয়ামেবারেতে কাজ করে, মনে হয় এটি একটি O (n ^ 2) অপারেশন হবে। পারফরম্যান্স যদি কোনও সমস্যা হয় (যদি বলুন যে আপনার তালিকাগুলি বড়) তবে আমি তালিকা 1 থেকে একটি হ্যাশসেট তৈরি করার পরামর্শ দেব এবং হ্যাশসেটের বাদে পদ্ধতি ব্যবহার করব।


9
Enumerable.Exceptঅভ্যন্তরীণভাবে ব্যবহার করে HashSetবা অনুরূপ কিছু। এটি স্পষ্টভাবে নিষ্পাপ O (n ^ 2) অ্যালগরিদম ব্যবহার করে না।
— জিম মিশেল

@ জিম মিশেল: আপনি ঠিক বলেছেন, গণনাযোগ্য x ডকুমেন্টেশন যে সম্পর্কে কিছু বলতে চান।
— ফোসন

1

এখানে আমার সমাধান:

    List<String> list1 = new List<String>();

    List<String> list2 = new List<String>();

    List<String> exceptValue = new List<String>();

foreach(String L1 in List1) 
{
    if(!List2.Contains(L1)
    {
         exceptValue.Add(L1);
    }
}
foreach(String L2 in List2) 
{
    if(!List1.Contains(L2)
    {
         exceptValue.Add(L2);
    }
}

-1

কিছুটা দেরি হলেও এখানে আমার জন্য সমাধান কাজ করছে

 var myBaseProperty = (typeof(BaseClass)).GetProperties();//get base code properties
                    var allProperty = entity.GetProperties()[0].DeclaringType.GetProperties();//get derived class property plus base code as it is derived from it
                    var declaredClassProperties = allProperty.Where(x => !myBaseProperty.Any(l => l.Name == x.Name)).ToList();//get the difference

উপরের উল্লেখ কোডটিতে আমি আমার বেস শ্রেণি এবং উত্পন্ন শ্রেণীর তালিকার মধ্যে বৈশিষ্ট্যগুলি পার্থক্য পেয়ে যাচ্ছি


-1
var resultList = checklist.Where(p => myList.All(l => p.value != l.value)).ToList();

দ্রষ্টব্য: ফলাফলের তালিকাটি আইটেমগুলি যা চেকলিস্টে উপস্থিত রয়েছে তবে
— মাইলিস্টে নেই

-2
List<ObjectC> _list_DF_BW_ANB = new List<ObjectC>();    
List<ObjectA> _listA = new List<ObjectA>();
List<ObjectB> _listB = new List<ObjectB>();

foreach (var itemB in _listB )
{     
    var flat = 0;
    foreach(var itemA in _listA )
    {
        if(itemA.ProductId==itemB.ProductId)
        {
            flat = 1;
            break;
        }
    }
    if (flat == 0)
    {
        _list_DF_BW_ANB.Add(itemB);
    }
}

উত্তর গৃহীত হওয়ার 6 বছর পরে এবং নতুন কোনও মূল্য যুক্ত করে না
— মিচ Wheat

-3

যদি আপনার উভয় তালিকাগুলি IEnumerable ইন্টারফেস প্রয়োগ করে তবে আপনি লিনকিউ ব্যবহার করে এটি অর্জন করতে পারেন।

list3 = list1.where(i => !list2.contains(i));

6
এবং যদি আপনার তালিকাগুলিতে প্রতিটি মিলিয়ন মিলিয়ন আইটেম থাকে তবে আপনি দীর্ঘ সময় অপেক্ষা করতে যাবেন। IEnumerable.Exceptপরিবর্তে ব্যবহার করুন।
— জিম মিশেল

3
হাঁ। আমার কাছে প্রায় 450 টি আইটেম রয়েছে এবং আমি এখনও অপেক্ষা করছি। এটি ব্যবহারে সতর্কতা অবলম্বন করুন।
— মার্নি কেজি 7 এসআইও

-3
        List<int> list1 = new List<int>();
        List<int> list2 = new List<int>();
        List<int> listDifference = new List<int>();

        foreach (var item1 in list1)
        {
            foreach (var item2 in list2)
            {
                if (item1 != item2)
                    listDifference.Add(item1);
            }
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.