সি # তে একটি তালিকা <টি> থেকে নকলগুলি সরান


487

সি # তে জেনেরিক তালিকাটি নকল করার জন্য কারও কাছেই দ্রুত পদ্ধতি আছে?


4
আপনি ফলাফলের উপাদান ক্রম সম্পর্কে যত্নশীল? এটি কিছু সমাধান বাদ দেবে।
কর্নেল আতঙ্ক

একটি ICollection<MyClass> withoutDuplicates = new HashSet<MyClass>(inputList);
ওলাইন

উত্তর:


227

সম্ভবত আপনার একটি হ্যাশসেট ব্যবহার করা বিবেচনা করা উচিত ।

এমএসডিএন লিঙ্ক থেকে:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        HashSet<int> evenNumbers = new HashSet<int>();
        HashSet<int> oddNumbers = new HashSet<int>();

        for (int i = 0; i < 5; i++)
        {
            // Populate numbers with just even numbers.
            evenNumbers.Add(i * 2);

            // Populate oddNumbers with just odd numbers.
            oddNumbers.Add((i * 2) + 1);
        }

        Console.Write("evenNumbers contains {0} elements: ", evenNumbers.Count);
        DisplaySet(evenNumbers);

        Console.Write("oddNumbers contains {0} elements: ", oddNumbers.Count);
        DisplaySet(oddNumbers);

        // Create a new HashSet populated with even numbers.
        HashSet<int> numbers = new HashSet<int>(evenNumbers);
        Console.WriteLine("numbers UnionWith oddNumbers...");
        numbers.UnionWith(oddNumbers);

        Console.Write("numbers contains {0} elements: ", numbers.Count);
        DisplaySet(numbers);
    }

    private static void DisplaySet(HashSet<int> set)
    {
        Console.Write("{");
        foreach (int i in set)
        {
            Console.Write(" {0}", i);
        }
        Console.WriteLine(" }");
    }
}

/* This example produces output similar to the following:
 * evenNumbers contains 5 elements: { 0 2 4 6 8 }
 * oddNumbers contains 5 elements: { 1 3 5 7 9 }
 * numbers UnionWith oddNumbers...
 * numbers contains 10 elements: { 0 2 4 6 8 1 3 5 7 9 }
 */

11
এর অবিশ্বাস্য দ্রুত ... 100.000 তালিকার সাথে স্ট্রিং 400s এবং 8MB র‌্যাম নেয়, আমার নিজের সমাধানটি 2.5s এবং 28MB নেয়, হ্যাশসেটটি 0.1s লাগে !!! এবং 11
এমবি

3
HashSet একটি সূচক নেই , তাই এটি ব্যবহার করা সর্বদা সম্ভব নয়। আমাকে একবারে নকল ছাড়াই বিশাল তালিকা তৈরি করতে হবে এবং তারপরে ListViewএটি ভার্চুয়াল মোডে ব্যবহার করতে হবে । এটি HashSet<>প্রথম তৈরি করা এবং তারপরে একে রূপান্তরিত করা List<>(অতএব ListViewসূচক অনুসারে আইটেমগুলি অ্যাক্সেস করতে পারে) অত্যন্ত দ্রুত ছিল। List<>.Contains()খুব ধীর।
সিনেটর

58
এই নির্দিষ্ট প্রসঙ্গে কীভাবে হ্যাশसेट ব্যবহার করতে হবে তার উদাহরণ থাকলে সেখানে সহায়তা করবে।
নাথান ম্যাককাস্কলে

23
এটি কীভাবে একটি উত্তর বিবেচনা করতে পারে? এটি একটি লিঙ্ক
এমকন্ট

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

813

যদি আপনি। নেট 3+ ব্যবহার করেন তবে আপনি লিনক ব্যবহার করতে পারেন।

List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();

14
এই কোডটি ব্যর্থ হবে। ডিসটিন্ট () একটি অনুমিত <টি> প্রদান করে। আপনাকে এটিতে .ToList () যুক্ত করতে হবে।
ljs

এই পদ্ধতির কেবল সাধারণ মান সহ তালিকার জন্য ব্যবহার করা যেতে পারে।
পোলারিস

20
না, এটি যে কোনও ধরণের অবজেক্টযুক্ত তালিকার সাথে কাজ করে। তবে আপনার ধরণের জন্য আপনাকে ডিফল্ট তুলনামূলকটিকে ওভাররাইড করতে হবে। ভালো লেগেছে: সার্বজনীন ওভাররাইড বুল সমান (অবজেক্ট আপত্তি) {...}
বাবু

1
আপনার ক্লাসগুলির সাথে ToString () এবং গেটহ্যাশকোড () কে ওভাররাইড করা সর্বদা একটি ভাল ধারণা যাতে এই ধরণের জিনিস কাজ করবে।
বি সেভেন

2
আপনি MoreLinQ নুগেট প্যাকেজটিও ব্যবহার করতে পারেন যার একটি .DistinctBy () এক্সটেনশন পদ্ধতি রয়েছে। বেশ দরকারী।
yu_ominae

178

কেমন:

var noDupes = list.Distinct().ToList();

.नेट 3.5?


এটি তালিকাটি নকল করে?
ডার্কগ্যাজে

1
@ ডার্কগাজে এটি কেবলমাত্র অনন্য এন্ট্রি সহ অন্য একটি তালিকা তৈরি করে। সুতরাং যে কোনও সদৃশ সরিয়ে ফেলা হবে এবং আপনি এমন একটি তালিকা রেখে গেছেন যেখানে প্রতিটি অবস্থানের আলাদা আলাদা অবজেক্ট রয়েছে।
hexagod

আইটেম কোডগুলি সদৃশ এবং অনন্য তালিকা
ভেঙ্কট

90

কেবল একই ধরণের একটি তালিকা সহ একটি হ্যাশসেট সূচনা করুন:

var noDupes = new HashSet<T>(withDupes);

বা, আপনি যদি চান একটি তালিকা ফেরত:

var noDupsList = new HashSet<T>(withDupes).ToList();

3
... এবং যদি আপনার List<T>ফলস্বরূপ ব্যবহারের প্রয়োজন হয়new HashSet<T>(withDupes).ToList()
টিম শেমলেটার

47

এটি বাছাই করুন, তারপরে একে অপরের পাশে দু'একটি পরীক্ষা করুন, কারণ সদৃশগুলি একসাথে ছড়িয়ে যাবে।

এটার মতো কিছু:

list.Sort();
Int32 index = list.Count - 1;
while (index > 0)
{
    if (list[index] == list[index - 1])
    {
        if (index < list.Count - 1)
            (list[index], list[list.Count - 1]) = (list[list.Count - 1], list[index]);
        list.RemoveAt(list.Count - 1);
        index--;
    }
    else
        index--;
}

মন্তব্য:

  • প্রতিটি অপসারণের পরে তালিকাটি অবলম্বন করা এড়াতে পিছন থেকে সামনের দিকে তুলনা করা হয়
  • এই উদাহরণটি এখন অদলবদল করতে সি # মান টিপলস ব্যবহার করে, আপনি যদি এটি ব্যবহার না করতে পারেন তবে উপযুক্ত কোডের বিকল্প দিন
  • শেষ ফলাফল আর বাছাই করা হয় না

1
যদি আমার ভুল না হয় তবে উপরে উল্লিখিত বেশিরভাগ পন্থাগুলি কেবল এই খুব রুটিনের বিমূর্ততা, তাই না? লাসে, আমি এখানে আপনার পদ্ধতি গ্রহণ করতাম কারণ এটি কীভাবে আমি ডেটা দিয়ে মানসিকভাবে চিত্রিত করি। তবে, এখন আমি কয়েকটি পরামর্শের মধ্যে পারফরম্যান্সের পার্থক্যে আগ্রহী।
আয়ান প্যাট্রিক হিউজেস

7
এগুলি প্রয়োগ করুন এবং তাদের সময় দিন, নিশ্চিত হওয়ার একমাত্র উপায়। এমনকি বিগ-ও স্বরলিপি আপনাকে প্রকৃত পারফরম্যান্স মেট্রিকগুলিতে সহায়তা করবে না, কেবলমাত্র একটি বৃদ্ধি প্রভাবের সম্পর্ক।
লাসে ভি কার্লসেন

1
আমি এই পদ্ধতির পছন্দ করি, এটি অন্যান্য ভাষাগুলিতে বেশি পোর্টেবল।
জেরি লিয়াং

10
এটা করবেন না। এটা খুব ধীর। RemoveAtএকটি একটি খুব ব্যয়বহুল অপারেশনList
Clément

1
ক্লিটমেন্ট ঠিক আছে। এটিকে উদ্ধার করার একটি উপায় হ'ল এটি এমন একটি পদ্ধতিতে মোড়ানো যা একটি গণকের সাথে ফল দেয় এবং কেবল স্বতন্ত্র মানগুলি ফিরিয়ে দেয়। বিকল্পভাবে আপনি কোনও নতুন অ্যারে বা তালিকায় মানগুলি অনুলিপি করতে পারেন।
জেহবার্ড 80

33

আমি এই আদেশটি ব্যবহার করতে চাই:

List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId)
                                                 .GroupBy(s => s.City)
                                                 .Select(grp => grp.FirstOrDefault())
                                                 .OrderBy(s => s.City)
                                                 .ToList();

আমার এই তালিকাগুলি আমার তালিকায় রয়েছে: আইডি, স্টোরনাম, শহর, পোস্টাল কোড কোড আমি ড্রপডাউনতে শহরগুলির তালিকা প্রদর্শন করতে চেয়েছিলাম যার সদৃশ মান রয়েছে। সমাধান: শহর অনুসারে গ্রুপ করুন তারপরে তালিকার জন্য প্রথমটি বেছে নিন।

আমি আসা করি এটা সাহায্য করবে :)


31

এটা আমার জন্য কাজ করেছে। সহজভাবে ব্যবহার

List<Type> liIDs = liIDs.Distinct().ToList<Type>();

আপনার পছন্দসই প্রকারের সাথে "টাইপ" প্রতিস্থাপন করুন।


1
বিভাজনটি লিনক-এ রয়েছে, সিস্টেম নয় Col সংগ্রহসমূহ the এমএসডিএন পৃষ্ঠা দ্বারা রিপোর্ট করা জেনেরিক।
অলমো

5
এই উত্তরটি (2012) এই পৃষ্ঠাতে অন্য দুটি উত্তর হিসাবে একই বলে মনে হচ্ছে যা 2008?
জন স্নাইডার

23

হিসাবে ক্রোনোজ বলেছেন। নেট 3.5 আপনি ব্যবহার করতে পারেন Distinct()

নেট 2 এ আপনি এটি অনুকরণ করতে পারেন:

public IEnumerable<T> DedupCollection<T> (IEnumerable<T> input) 
{
    var passedValues = new HashSet<T>();

    // Relatively simple dupe check alg used as example
    foreach(T item in input)
        if(passedValues.Add(item)) // True if item is new
            yield return item;
}

এটি কোনও সংগ্রহ হ্রাস করতে ব্যবহৃত হতে পারে এবং মূল ক্রমে মানগুলি ফিরিয়ে দেয়।

এটি সংগ্রহ থেকে ফিল্টার করা সাধারণত (যেমন Distinct()এবং এই নমুনা উভয়ই ) এর থেকে আইটেমগুলি সরিয়ে ফেলার চেয়ে দ্রুততর ।


যদিও এই পদ্ধতির সমস্যাটি হ'ল হ্যাশসেটের বিপরীতে এটি ও (এন ^ 2) -ইশ। তবে এটি কি করছে তা অন্তত স্পষ্ট।
তামাস সিজনেজে

1
@ ডিআরজোকপু - আসলে আমি বুঝতে পারি নি যে HashSetনির্মাতা ছাড়িয়েছেন, যা বেশিরভাগ পরিস্থিতিতে এটি আরও ভাল করে তোলে। যাইহোক, এটি বাছাই ক্রম সংরক্ষণ করবে, যা একটি HashSetনয়।
কিথ

1
হ্যাশসেট <টি> পরিচয় হয়েছিল 3.5
কাঁটা th

1
@ সত্যিই? ট্র্যাক রাখা তাই কঠিন। সেক্ষেত্রে আপনি কেবল Dictionary<T, object>পরিবর্তে ব্যবহার করতে পারেন , .Containsসাথে .ContainsKeyএবং এর .Add(item)সাথে প্রতিস্থাপন করতে পারেন.Add(item, null)
কীথ

@ কিথ, আমার পরীক্ষার অনুসারে HashSetঅর্ডার সংরক্ষণ Distinct()করে যখন না হয়।
ডেনিস টি

13

কোনও এক্সটেনশন পদ্ধতিটি যেতে পারে একটি শালীন উপায় ... এরকম কিছু:

public static List<T> Deduplicate<T>(this List<T> listToDeduplicate)
{
    return listToDeduplicate.Distinct().ToList();
}

এবং তারপরে এই জাতীয় কল করুন, উদাহরণস্বরূপ:

List<int> myFilteredList = unfilteredList.Deduplicate();

11

জাভাতে (আমি ধরে নিচ্ছি যে # # কম-বেশি অভিন্ন):

list = new ArrayList<T>(new HashSet<T>(list))

আপনি যদি সত্যিই মূল তালিকাটি পরিবর্তন করতে চান:

List<T> noDupes = new ArrayList<T>(new HashSet<T>(list));
list.clear();
list.addAll(noDupes);

অর্ডার সংরক্ষণের জন্য, কেবলমাত্র হ্যাশসেটকে লিঙ্কডহ্যাশসেটের সাথে প্রতিস্থাপন করুন।


5
সি # তে এটি হবে: তালিকা <টি> নোডুপেস = নতুন তালিকা <টি> (নতুন হ্যাশসেট <টি> (তালিকা)); list.Clear (); list.AddRange (noDupes);
সোমবার

সি # তে, এটি আরও সহজ: var noDupes = new HashSet<T>(list); list.Clear(); list.AddRange(noDupes);:)
নওফাল

10

এটি স্বতন্ত্র (ডুপ্লিকেট উপাদান ছাড়াই উপাদানগুলি) নেয় এবং এটিকে আবার একটি তালিকায় রূপান্তর করে:

List<type> myNoneDuplicateValue = listValueWithDuplicate.Distinct().ToList();

9

লিনকের ইউনিয়ন পদ্ধতিটি ব্যবহার করুন ।

দ্রষ্টব্য: এই সমাধানটির উপস্থিতির বাইরে লিনকের কোনও জ্ঞানের প্রয়োজন নেই।

কোড

আপনার ক্লাস ফাইলের শীর্ষে নিম্নলিখিতটি যুক্ত করে শুরু করুন:

using System.Linq;

এখন, আপনি নামক কোনও অবজেক্ট থেকে নকলগুলি সরাতে নিম্নলিখিতটি ব্যবহার করতে পারেন obj1:

obj1 = obj1.Union(obj1).ToList();

দ্রষ্টব্য: obj1আপনার বস্তুর নাম পরিবর্তন করুন।

কিভাবে এটা কাজ করে

  1. ইউনিয়ন কমান্ড দুটি উত্স অবজেক্টের প্রতিটি প্রবেশের একটি তালিকাভুক্ত করে। যেহেতু obj1 উভয় উত্স অবজেক্ট, এটি প্রতিটি এন্ট্রির একটিতেজেজ 1 হ্রাস করে।

  2. ToList()একটি নতুন তালিকা ফেরৎ। এটি প্রয়োজনীয়, কারণ লিনক আদেশের Unionপরিবর্তে মূল তালিকাটি পরিবর্তন বা নতুন তালিকা ফিরিয়ে দেওয়ার পরিবর্তে ফলাফলকে একটি ফলমূল হিসাবে প্রত্যাবর্তন করে।


7

সহায়ক হিসাবে (লিনক ব্যতীত):

public static List<T> Distinct<T>(this List<T> list)
{
    return (new HashSet<T>(list)).ToList();
}

আমার মনে হয় ডিসট্রিন্টটি ইতিমধ্যে নেওয়া হয়েছে। তা ছাড়া (যদি আপনি নামটির নাম পরিবর্তন করেন) এটি কাজ করা উচিত।
আন্দ্রেয়াস রেফ 12

6

আপনি যত্নশীল না থাকে তাহলে আপনি শুধু একটি বা আইটেম ঠেলা পারেন HashSet, যদি আপনি না অর্ডার আপনি ভালো কিছু করতে পারেন বজায় রাখতে চান:

var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
    if (hs.Add(t))
        unique.Add(t);

বা লিনক উপায়:

var hs = new HashSet<T>();
list.All( x =>  hs.Add(x) );

সম্পাদনা:HashSet পদ্ধতি O(N)সময় এবং O(N)স্থান যখন বাছাই এবং তারপর অনন্য উপার্জন (যেমন @ দ্বারা প্রস্তাবিত lassevk এবং অন্যদের) হল O(N*lgN)সময় এবং O(1)স্থান, তাই এটি আমার তাই পরিষ্কার না (হিসাবে এটি প্রথম নজরে ছিল) যে বাছাই পথ নিকৃষ্ট (আমার অস্থায়ী ডাউন ভোটের জন্য ক্ষমা ...)


6

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

public static void RemoveAdjacentDuplicates<T>(this List<T> List, IComparer<T> Comparer)
{
    int NumUnique = 0;
    for (int i = 0; i < List.Count; i++)
        if ((i == 0) || (Comparer.Compare(List[NumUnique - 1], List[i]) != 0))
            List[NumUnique++] = List[i];
    List.RemoveRange(NumUnique, List.Count - NumUnique);
}

5

নুগেটের মাধ্যমে মোরেলিংকিউ প্যাকেজ ইনস্টল করা , আপনি কোনও সম্পত্তি দ্বারা সহজেই পৃথক অবজেক্টের তালিকা করতে পারেন

IEnumerable<Catalogue> distinctCatalogues = catalogues.DistinctBy(c => c.CatalogueCode); 

3

অনুলিপি তালিকায় যুক্ত করা হয়নি তা সহজ করে নিশ্চিত করা সহজ হতে পারে।

if(items.IndexOf(new_item) < 0) 
    items.add(new_item)

1
আমি বর্তমানে এটি এর মতো করে দিচ্ছি তবে ডুপ্লিকেটগুলির জন্য যত বেশি পরীক্ষা আপনার চেক লাগবে তত বেশি ries
রবার্ট স্ট্রাচ

আমারও এখানে একই সমস্যা আছে। আমি List<T>.Containsপ্রতিবার এই পদ্ধতিটি ব্যবহার করছি তবে এক হাজারেরও বেশি এন্ট্রি সহ। এই প্রক্রিয়াটি আমার অ্যাপ্লিকেশনটিকে ধীর করে দেয়। আমি এর List<T>.Distinct().ToList<T>()পরিবর্তে প্রথমটি ব্যবহার করছি ।
আরপিডিজেস

এই পদ্ধতিটি খুব ধীর
ডার্কগ্রাজে

3

আপনি ইউনিয়ন ব্যবহার করতে পারেন

obj2 = obj1.Union(obj1).ToList();

7
এটি কেন কাজ করবে তা ব্যাখ্যা অবশ্যই উত্তরটি আরও ভাল করে তুলবে
আইগোর বি

2

.Net 2.0 এ অন্য উপায়

    static void Main(string[] args)
    {
        List<string> alpha = new List<string>();

        for(char a = 'a'; a <= 'd'; a++)
        {
            alpha.Add(a.ToString());
            alpha.Add(a.ToString());
        }

        Console.WriteLine("Data :");
        alpha.ForEach(delegate(string t) { Console.WriteLine(t); });

        alpha.ForEach(delegate (string v)
                          {
                              if (alpha.FindAll(delegate(string t) { return t == v; }).Count > 1)
                                  alpha.Remove(v);
                          });

        Console.WriteLine("Unique Result :");
        alpha.ForEach(delegate(string t) { Console.WriteLine(t);});
        Console.ReadKey();
    }

2

সমাধানের জন্য অনেকগুলি উপায় রয়েছে - নীচে তালিকার সদৃশ ইস্যুগুলি এর মধ্যে একটি:

List<Container> containerList = LoadContainer();//Assume it has duplicates
List<Container> filteredList = new  List<Container>();
foreach (var container in containerList)
{ 
  Container duplicateContainer = containerList.Find(delegate(Container checkContainer)
  { return (checkContainer.UniqueId == container.UniqueId); });
   //Assume 'UniqueId' is the property of the Container class on which u r making a search

    if(!containerList.Contains(duplicateContainer) //Add object when not found in the new class object
      {
        filteredList.Add(container);
       }
  }

চিয়ার্স রবি গণেশান


2

এখানে একটি সহজ সমাধান রয়েছে যার জন্য হার্ড-টু-পঠিত লিনকিউ বা তালিকার কোনও পূর্ববর্তী বাছাইয়ের প্রয়োজন নেই।

   private static void CheckForDuplicateItems(List<string> items)
    {
        if (items == null ||
            items.Count == 0)
            return;

        for (int outerIndex = 0; outerIndex < items.Count; outerIndex++)
        {
            for (int innerIndex = 0; innerIndex < items.Count; innerIndex++)
            {
                if (innerIndex == outerIndex) continue;
                if (items[outerIndex].Equals(items[innerIndex]))
                {
                    // Duplicate Found
                }
            }
        }
    }

এই পদ্ধতির সাহায্যে সদৃশ আইটেমগুলির উপর আপনার আরও নিয়ন্ত্রণ রয়েছে। আরও যদি আপনার আপডেট করার জন্য একটি ডাটাবেস থাকে। ইনারআইএনডেক্সের জন্য, কেন প্রতিবারের থেকে শুরু করে বাইরের ইনডেক্স + 1 থেকে শুরু হচ্ছে না?
নোলমা ইনফরমেশনিক

2

ডেভিড জে এর উত্তর একটি ভাল পদ্ধতি, অতিরিক্ত জিনিস, বাছাই ইত্যাদির প্রয়োজন নেই তবে তবে এটি উন্নত করা যেতে পারে:

for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)

সুতরাং বাইরের লুপটি পুরো তালিকার শীর্ষে নীচে যায়, তবে অভ্যন্তরীণ লুপটি নীচে চলে যায় "যতক্ষণ না বাইরের লুপের অবস্থান পৌঁছে যায়"।

বাইরের লুপটি নিশ্চিত করে যে পুরো তালিকাটি প্রক্রিয়া করা হয়েছে, অভ্যন্তরীণ লুপটি প্রকৃত নকলগুলি সন্ধান করে, কেবলমাত্র সেই অংশে ঘটতে পারে যে বাহ্যিক লুপটি এখনও প্রক্রিয়াজাত হয়নি।

অথবা আপনি যদি অভ্যন্তরীণ লুপটির জন্য নীচে করতে না চান তবে আপনার অভ্যন্তরীণ লুপটি বহির্মুখী সূচনা +1 এ শুরু হতে পারে।


2

সমস্ত উত্তর তালিকা কপি করে, বা একটি নতুন তালিকা তৈরি করে, বা ধীর ফাংশন ব্যবহার করে, বা কেবল বেদনাদায়ক ধীরে ধীরে।

আমার বোঝার জন্য, এটি আমার জানা সবচেয়ে দ্রুত এবং সস্তার পদ্ধতি (এছাড়াও, রিয়েল-টাইম ফিজিক্স অপ্টিমাইজেশনে বিশেষজ্ঞ বিশেষ অভিজ্ঞ প্রোগ্রামার দ্বারা সমর্থিত)।

// Duplicates will be noticed after a sort O(nLogn)
list.Sort();

// Store the current and last items. Current item declaration is not really needed, and probably optimized by the compiler, but in case it's not...
int lastItem = -1;
int currItem = -1;

int size = list.Count;

// Store the index pointing to the last item we want to keep in the list
int last = size - 1;

// Travel the items from last to first O(n)
for (int i = last; i >= 0; --i)
{
    currItem = list[i];

    // If this item was the same as the previous one, we don't want it
    if (currItem == lastItem)
    {
        // Overwrite last in current place. It is a swap but we don't need the last
       list[i] = list[last];

        // Reduce the last index, we don't want that one anymore
        last--;
    }

    // A new item, we store it and continue
    else
        lastItem = currItem;
}

// We now have an unsorted list with the duplicates at the end.

// Remove the last items just once
list.RemoveRange(last + 1, size - last - 1);

// Sort again O(n logn)
list.Sort();

চূড়ান্ত ব্যয় হ'ল:

nlogn + n + nlogn = n + 2nlogn = O ( nlogn ) যা বেশ সুন্দর।

সরানরেঞ্জ সম্পর্কে নোট: যেহেতু আমরা তালিকার গণনা নির্ধারণ করতে এবং ফান ফ্যাশনগুলি অপসারণ করা এড়াতে পারি না, তাই আমি এই অপারেশনের গতি ঠিক জানি না তবে আমি অনুমান করি যে এটি সবচেয়ে দ্রুততম উপায়।


2

আপনার যদি টো ক্লাস থাকে Productএবং Customerআমরা তাদের তালিকা থেকে সদৃশ আইটেমগুলি সরাতে চাই

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

public class Customer
{
    public int Id { get; set; }
    public string CustomerName { get; set; }

}

আপনাকে অবশ্যই নীচের ফর্মটিতে জেনেরিক শ্রেণি সংজ্ঞায়িত করতে হবে

public class ItemEqualityComparer<T> : IEqualityComparer<T> where T : class
{
    private readonly PropertyInfo _propertyInfo;

    public ItemEqualityComparer(string keyItem)
    {
        _propertyInfo = typeof(T).GetProperty(keyItem, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
    }

    public bool Equals(T x, T y)
    {
        var xValue = _propertyInfo?.GetValue(x, null);
        var yValue = _propertyInfo?.GetValue(y, null);
        return xValue != null && yValue != null && xValue.Equals(yValue);
    }

    public int GetHashCode(T obj)
    {
        var propertyValue = _propertyInfo.GetValue(obj, null);
        return propertyValue == null ? 0 : propertyValue.GetHashCode();
    }
}

তারপরে, আপনি আপনার তালিকার সদৃশ আইটেমগুলি সরাতে পারেন।

var products = new List<Product>
            {
                new Product{ProductName = "product 1" ,Id = 1,},
                new Product{ProductName = "product 2" ,Id = 2,},
                new Product{ProductName = "product 2" ,Id = 4,},
                new Product{ProductName = "product 2" ,Id = 4,},
            };
var productList = products.Distinct(new ItemEqualityComparer<Product>(nameof(Product.Id))).ToList();

var customers = new List<Customer>
            {
                new Customer{CustomerName = "Customer 1" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
                new Customer{CustomerName = "Customer 2" ,Id = 5,},
            };
var customerList = customers.Distinct(new ItemEqualityComparer<Customer>(nameof(Customer.Id))).ToList();

এই কোড দ্বারা নকল আইটেমগুলি সরিয়ে Idআপনি যদি অন্য সম্পত্তি দ্বারা নকল আইটেমগুলি সরাতে চান, আপনি nameof(YourClass.DuplicateProperty) একই পরিবর্তন করতে পারেন nameof(Customer.CustomerName)তবে CustomerNameসম্পত্তি দ্বারা নকল আইটেমগুলি সরিয়ে ফেলুন ।


1
  public static void RemoveDuplicates<T>(IList<T> list )
  {
     if (list == null)
     {
        return;
     }
     int i = 1;
     while(i<list.Count)
     {
        int j = 0;
        bool remove = false;
        while (j < i && !remove)
        {
           if (list[i].Equals(list[j]))
           {
              remove = true;
           }
           j++;
        }
        if (remove)
        {
           list.RemoveAt(i);
        }
        else
        {
           i++;
        }
     }  
  }

1

একটি সাধারণ স্বজ্ঞাত বাস্তবায়ন:

public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
    List<PointF> result = new List<PointF>();

    for (int i = 0; i < listPoints.Count; i++)
    {
        if (!result.Contains(listPoints[i]))
            result.Add(listPoints[i]);
        }

        return result;
    }

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