সি # বাছাইযোগ্য সংগ্রহ যা ডুপ্লিকেট কীগুলিকে অনুমতি দেয়


97

আমি একটি ক্রম সেট করার জন্য একটি প্রোগ্রাম লিখছি যাতে প্রতিবেদনটিতে বিভিন্ন অবজেক্ট উপস্থিত হবে। ক্রমটি হল এক্সেল স্প্রেডশিটে ওয়াই পজিশন (সেল)।

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

SortedList list = new SortedList();

Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);

h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);

আমি জানি যে SortedListthisশ্বর এটির অনুমতি দেবেন না এবং আমি বিকল্পটির জন্য অনুসন্ধান করছি। আমি নকলগুলি অপসারণ করতে চাই না এবং ইতিমধ্যে চেষ্টা করেছি List<KeyValuePair<int, object>>

ধন্যবাদ


4
সংগ্রহের সদস্যদের প্রাথমিক তালিকা দেওয়ার পরে কি সন্নিবেশ / অপসারণ সমর্থন করা দরকার ?
আনি

4
আপনি চেষ্টা করার পরে কি কাজ হয়নি List?
diceguyd30

আমি ঠিক বাছাই করতে চাই এবং অবজেক্টটি পেতে চাই না। বরং আমি পুরো সাজানো তালিকা পেতে চাই। সুতরাং নীচের উদাহরণে, উভয় শিরোলেখী অবজেক্টগুলি থাকা উচিত এবং ক্রমানুসারে একে অপরের নীচে। যদি আমি এক্সপোস = 2 দিয়ে অন্য শিরোনামের বস্তুটি যুক্ত করি তবে তালিকায় আমার 3 টি অবজেক্ট, এক্সপোস = 1 এবং 2 তৃতীয় এক্সপোস = 2 হিসাবে থাকা উচিত
মায়ুর কোটলিকার

কেবলমাত্র একটি নোট: আমি যখন এই ধরণের পরিস্থিতির মুখোমুখি হই তখন আমি দেখতে পাই যে জেনেরিক তালিকাটি আইটেমগুলির জন্য স্বল্প-পরিচিত বাইনারি অনুসন্ধান আচরণের সাথে একত্রিত হয়ে বিস্ময়ের কাজ করে না
জে

উত্তর:


79

আপনার নিজস্ব আইকম্পার ব্যবহার করুন!

ইতিমধ্যে কিছু অন্যান্য উত্তরে যেমন বলা হয়েছে, আপনার নিজের তুলনামূলক ক্লাস ব্যবহার করা উচিত। এই জন্য আমি একটি জেনেরিক আইকোপ্যামার ক্লাস ব্যবহার করি, যা আইকোম্যাপারেবল কার্যকর করে এমন কোনও কিছু নিয়ে কাজ করে:

/// <summary>
/// Comparer for comparing two keys, handling equality as beeing greater
/// Use this Comparer e.g. with SortedLists or SortedDictionaries, that don't allow duplicate keys
/// </summary>
/// <typeparam name="TKey"></typeparam>
public class DuplicateKeyComparer<TKey>
                :
             IComparer<TKey> where TKey : IComparable
{
    #region IComparer<TKey> Members

    public int Compare(TKey x, TKey y)
    {
        int result = x.CompareTo(y);

        if (result == 0)
            return 1;   // Handle equality as beeing greater
        else
            return result;
    }

    #endregion
}

নতুন সোর্টার্ডলিস্ট, সোর্টড ডিকোরিয়ানা ইত্যাদি ইনস্ট্যান্স করার সময় আপনি এটি ব্যবহার করবেন:

SortedList<int, MyValueClass> slist = new SortedList<int, MyValueClass>(new DuplicateKeyComparer<int>());

এখানে int হল কীটি যা সদৃশ হতে পারে।


43
তবে আপনি এটি থেকে কোনও কী মুছে ফেলতে পারবেন না।
শাশ্বত

11
হ্যাঁ ঠিক আছে, শাওয়াত! আপনি সরান (কী) বা ইনডেক্স অফফিকে (কী) ব্যবহার করতে পারবেন না, কারণ তুলনাকারী কখনই মূল সমতার সিগন্যালে 0 ফেরায় না। তবে আইটেমগুলির সূচক থাকলে আপনি মুছে ফেলতে পারেন (সূচক)।
নাস্টারব্যাক্স

4
আমিও একই সমস্যার মুখোমুখি হয়েছি, আমি ব্যবহার করেছি SortedDictionary। এটি পাশাপাশি সরানোর অনুমতি দেয়।
শাশ্বত

10
মনে রাখবেন ভঙ্গ করছে reflexivity আপনার comparer এই উপায়। এটি ছাত্রলীগের জিনিসগুলিকে (এবং ইচ্ছা) ভাঙ্গতে পারে।
ঘোড়

4
এটি অর্ডার রাখতে আসলে -1 ফিরতে হবে
এম.কাজেম আখগারি

16

আপনি নিরাপদে তালিকা <> ব্যবহার করতে পারেন। তালিকার একটি বাছাই করার পদ্ধতি রয়েছে, একটি ওভারলোড যা আইকোম্পারকে গ্রহণ করে। আপনি নিজের নিজস্ব বাছাই করা বর্গ তৈরি করতে পারেন। এখানে একটি উদাহরণ:

private List<Curve> Curves;
this.Curves.Sort(new CurveSorter());

public class CurveSorter : IComparer<Curve>
{
    public int Compare(Curve c1, Curve c2)
    {
        return c2.CreationTime.CompareTo(c1.CreationTime);
    }
}

4
আমি ঠিক বাছাই করতে চাই এবং অবজেক্টটি পেতে চাই না। বরং আমি পুরো বাছাই করা তালিকা পেতে চাই। সুতরাং নীচের উদাহরণে, উভয় শিরোলেখী অবজেক্টগুলি থাকা উচিত এবং ক্রমানুসারে একে অপরের নীচে। যদি আমি এক্সপোস = 2 দিয়ে অন্য শিরোনামের বস্তুটি যুক্ত করি তবে তালিকায় আমার 3 টি অবজেক্ট, এক্সপোস = 1 এবং 2 তৃতীয় এক্সপোস = 2 হিসাবে থাকা উচিত
মায়ুর কোটলিকার

4
ঠিক আপনারা বলার অর্থ, তালিকার তালিকায় যে কোনও সময় একটি উপাদান isোকানো হবে ঠিক ততক্ষণ এটিকে সঠিক অনুসারে বাছাই করা উচিত। ভুল হলে আমাকে সংশোধন করুন। আমাকে একবার দেখে নেওয়া যাক, অল্প মুহূর্তে ফিরে আসবেন
দিপ্তি মেহতা

নোট করুন যে তালিকা <T>। সাজান সংগ্রহের আকারের উপর নির্ভর করে একাধিক বাছাই করা অ্যালগরিদম ব্যবহার করে এবং সেগুলি সবই স্থিতিশীল নয়। সুতরাং সমষ্টিটির সাথে তুলনা করা সামগ্রীতে যুক্ত হওয়া বস্তুগুলি তাদের যুক্ত করা ক্রমে উপস্থিত নাও হতে পারে।
নিঃশব্দ স্বর

আমি এই বিকল্পটির সাথে গিয়েছিলাম যাতে আমি কোনও অভিধানে ফাংশন হ্রাস প্রয়োগের মাধ্যমে কীভ্যালু পেয়ারগুলির প্রচুর পরিমাণে তৈরি বন্ধ করতে পারি
ক্রিস মেরিসিক

10

আমি নিম্নলিখিত ব্যবহার:

public class TupleList<T1, T2> : List<Tuple<T1, T2>> where T1 : IComparable
{
    public void Add(T1 item, T2 item2)
    {
        Add(new Tuple<T1, T2>(item, item2));
    }

    public new void Sort()
    {
        Comparison<Tuple<T1, T2>> c = (a, b) => a.Item1.CompareTo(b.Item1);
        base.Sort(c);
    }

}

আমার পরীক্ষার কেস:

[TestMethod()]
    public void SortTest()
    {
        TupleList<int, string> list = new TupleList<int, string>();
        list.Add(1, "cat");
        list.Add(1, "car");
        list.Add(2, "dog");
        list.Add(2, "door");
        list.Add(3, "elephant");
        list.Add(1, "coconut");
        list.Add(1, "cab");
        list.Sort();
        foreach(Tuple<int, string> tuple in list)
        {
            Console.WriteLine(string.Format("{0}:{1}", tuple.Item1,tuple.Item2));
        }
        int expected_first = 1;
        int expected_last = 3;
        int first = list.First().Item1;  //requires using System.Linq
        int last = list.Last().Item1;    //requires using System.Linq
        Assert.AreEqual(expected_first, first);
        Assert.AreEqual(expected_last, last);
    }

আউটপুট:

1:cab
1:coconut
1:car
1:cat
2:door
2:dog
3:elephant

TETle .NET এর সমস্ত রিলিজে পাওয়া যায় না, তবে কীভ্যালিউপায়ার <কে, ভি>
রূবেণ

6

সমস্যাটি হ'ল ডেটা স্ট্রাকচার ডিজাইনটি প্রয়োজনীয়তার সাথে মেলে না: একই এক্সপোসের জন্য বেশ কয়েকটি শিরোনাম সংরক্ষণ করা প্রয়োজন। অতএব, SortedList<XPos, value>একটি মান থাকা উচিত নয় Header, কিন্তু একটি মান List<Header>। এটি একটি সহজ এবং ছোট পরিবর্তন, তবে এটি সমস্ত সমস্যার সমাধান করে এবং অন্যান্য প্রস্তাবিত সমাধানের মতো নতুন সমস্যা তৈরি করা এড়ানো (নীচে ব্যাখ্যা দেখুন):

using System;
using System.Collections.Generic;

namespace TrySortedList {
  class Program {

    class Header {
      public int XPos;
      public string Name;
    }

    static void Main(string[] args) {
      SortedList<int, List<Header>> sortedHeaders = new SortedList<int,List<Header>>();
      add(sortedHeaders, 1, "Header_1");
      add(sortedHeaders, 1, "Header_2");
      add(sortedHeaders, 2, "Header_3");
      foreach (var headersKvp in sortedHeaders) {
        foreach (Header header in headersKvp.Value) {
          Console.WriteLine(header.XPos + ": " + header.Name);
        }
      }
    }

    private static void add(SortedList<int, List<Header>> sortedHeaders, int xPos, string name) {
      List<Header> headers;
      if (!sortedHeaders.TryGetValue(xPos, out headers)){
        headers = new List<Header>();
        sortedHeaders[xPos] = headers;
      }
      headers.Add(new Header { XPos = xPos, Name = name });
    }
  }
}

Output:
1: Header_1
1: Header_2
2: Header_3

দয়া করে মনে রাখবেন যে একটি "মজাদার" কী যুক্ত করা, যেমন একটি এলোমেলো সংখ্যা যুক্ত করা বা একই ভ্যালু সহ 2 এক্সপোস ভান করা অন্যান্য অনেক সমস্যার জন্য ভিন্ন সীসা। উদাহরণস্বরূপ কোনও নির্দিষ্ট শিরোলেখ অপসারণ করা কঠিন বা এমনকি অসম্ভব হয়ে পড়ে।

আরও মনে রাখবেন যে বাছাই করা পারফরম্যান্সটি আরও ভাল যদি প্রত্যেকের List<Header>তুলনায় খুব কম লোককে বাছাই করতে হয় Header। উদাহরণ: যদি 100 এক্সপোস থাকে এবং প্রত্যেকের 100 টি শিরোনাম থাকে তবে 100 এর Headerবিপরীতে 10000 বাছাই করা দরকার List<Header>

অবশ্যই, এই সমাধানটির একটি অসুবিধাও রয়েছে: যদি কেবলমাত্র 1 টি শিরোলেখ সহ অনেকগুলি এক্সপোস থাকে, তবে অনেকগুলি তালিকা তৈরি করা দরকার যা কিছুটা ওভারহেড।


এটি সবচেয়ে সহজ সমাধান। সোর্টার্ডডেটরিও পরীক্ষা করে দেখুন, এটি কিছু ক্ষেত্রে একই রকম।
হোগান

এটি সত্যিই একটি ভাল সমাধান। কেউ খুব সহজেই কিছু কার্যকারিতা সংগ্রহের বস্তুতে সেই কার্যকারিতাটি लपेटতে পারে এবং এটি বেশ কার্যকর হবে। ভাল চিন্তা, পিটার ভাগ করে নেওয়ার জন্য ধন্যবাদ!
অ্যাডাম পি

5

সহজ সমাধান (উপরের সকলের তুলনায়): ব্যবহার করুন SortedSet<T>, এটি একটি IComparer<SortableKey>শ্রেণি গ্রহণ করে , তারপরে এইভাবে তুলনা পদ্ধতিটি প্রয়োগ করুন:

public int Compare(SomeClass x, SomeClass y)
{
    var compared = x.SomeSortableKeyTypeField.CompareTo(y.SomeSortableKeyTypeField);
    if (compared != 0)
        return compared;

    // to allow duplicates
    var hashCodeCompare = x.GetHashCode().CompareTo(y.GetHashCode());
    if (hashCodeCompare != 0)
        return hashCodeCompare;

    if (Object.ReferenceEquals(x, y))
        return 0;

    // for weird duplicate hashcode cases, throw as below or implement your last chance comparer
    throw new ComparisonFailureException();

}

4
আমি সোর্টসেট <টি> ব্যবহার করেছি এবং টি এর নিজস্ব বর্ধিত আইটি ছিল যা প্রতিটি ইনস্ট্যান্টেশনে প্রতিটি টি-তে বীমা করানোর জন্য বর্ধিত হয় এমনকি অন্যান্য ক্ষেত্রগুলির (গুলি) একই হয়।
স্কাইচান

4
তুলনার জন্য গেটহ্যাশকোড বিপজ্জনক। অপ্রত্যাশিত মিথ্যা সদৃশ হতে পারে। এটি বেশিরভাগ সময় কাজ করতে পারে তবে আমি এটিকে কখনও গুরুতর কোনও কারণে ব্যবহার করব না।
হোগান

4

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

প্রথমত, আমি একটি ক্লাস তৈরি করেছি যা ক্লাসগুলির জন্য আমার অবজেক্টগুলিকে আবদ্ধ করবে (শিরোনাম, পাদলেখ ইত্যাদি)

public class MyPosition
{
    public int Position { get; set; }
    public object MyObjects{ get; set; }
}

সুতরাং এই শ্রেণিটি অবজেক্টগুলিকে ধরে রাখার কথা, এবং প্রতিটি বস্তুর পোস্টএক্স ইন্ট পজিশন হিসাবে যায়

List<MyPosition> Sequence= new List<MyPosition>();
Sequence.Add(new MyPosition() { Position = 1, Headerobject });
Sequence.Add(new MyPosition() { Position = 2, Headerobject1 });
Sequence.Add(new MyPosition() { Position = 1, Footer });

League.Sort((PosA, PosB) => PosA.Position.CompareTo(PosB.Position));

পরিশেষে যা পাই তা হ'ল সাজানো "সিকোয়েন্স" তালিকা।


2

আপনি কি চেষ্টা করেছেন Lookup<TKey, TElement>যে সদৃশ কীগুলিকে http://msdn.microsoft.com/en-us/library/bb460184.aspx টির অনুমতি দেবে


ধন্যবাদ আমার সমস্যাটি হ'ল বস্তুগুলি কেবল এক ধরণের হবে না (কেবল শিরোনাম নয়), সেগুলি পরিবর্তিত হতে পারে (পাদলেখ বলতে পারি, সাইডবার ইত্যাদি) তবে প্রত্যেকটির এক্সপোস থাকবে
মায়ুর কোটলিকর

এছাড়াও, Lookupআমি বিশ্বাস করি যে কোনও পাবলিক কনস্ট্রাক্টর নেই । এই কাছাকাছি কোন ভাল উপায়?
জেফ বি

4
@ জেফব্রিডগম্যান আপনি লিনকের উপর নির্ভর করতে হবে। আপনি কি করতে পারেন ToLookupকোনো IEnumerable<T>
নওফাল

8
হ্যাঁ এটি সদৃশ কীগুলিকে অনুমতি দেয় তবে এটি কিছু সাজানো রাখে না!
রোমান স্টারকভ

2

আপনি সোর্টার্ডলিস্টটি ব্যবহার করতে পারেন, টিকেয়ের জন্য আপনার মান এবং টিভিয়ালুর জন্য ইন্ট (গণনা) ব্যবহার করতে পারেন।

এখানে একটি নমুনা রয়েছে: এমন একটি ফাংশন যা কোনও শব্দের অক্ষর বাছাই করে।

    private string sortLetters(string word)
    {
        var input = new System.Collections.Generic.SortedList<char, int>();

        foreach (var c in word.ToCharArray())
        {
            if (input.ContainsKey(c))
                input[c]++;
            else
                input.Add(c, 1);
        }

        var output = new StringBuilder();

        foreach (var kvp in input)
        {
            output.Append(kvp.Key, kvp.Value);
        }

        string s;

        return output.ToString();

    }

2

এই সংগ্রহ শ্রেণিটি সদৃশগুলি বজায় রাখবে এবং সদৃশটির জন্য সাজানোর ক্রম সন্নিবেশ করবে। কৌশলটি হ'ল স্থিতিশীল ক্রম বজায় রাখতে আইটেমগুলিকে একটি অনন্য মান দিয়ে ট্যাগ করা হয়। তারপরে আমরা এগুলিকে একটি আইকোলিকেশন ইন্টারফেসে আবদ্ধ করি।

public class SuperSortedSet<TValue> : ICollection<TValue>
{
    private readonly SortedSet<Indexed<TValue>> _Container;
    private int _Index = 0;
    private IComparer<TValue> _Comparer;

    public SuperSortedSet(IComparer<TValue> comparer)
    {
        _Comparer = comparer;
        var c2 = new System.Linq.Comparer<Indexed<TValue>>((p0, p1) =>
        {
            var r = _Comparer.Compare(p0.Value, p1.Value);
            if (r == 0)
            {
                if (p0.Index == -1
                    || p1.Index == -1)
                    return 0;

                return p0.Index.CompareTo(p1.Index);

            }
            else return r;
        });
        _Container = new SortedSet<Indexed<TValue>>(c2);
    } 

    public IEnumerator<TValue> GetEnumerator() { return _Container.Select(p => p.Value).GetEnumerator(); }

    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

    public void Add(TValue item) { _Container.Add(Indexed.Create(_Index++, item)); }

    public void Clear() { _Container.Clear();}

    public bool Contains(TValue item) { return _Container.Contains(Indexed.Create(-1,item)); }

    public void CopyTo(TValue[] array, int arrayIndex)
    {
        foreach (var value in this)
        {
            if (arrayIndex >= array.Length)
            {
                throw new ArgumentException("Not enough space in array");
            }
            array[arrayIndex] = value;
            arrayIndex++;
        }
    }

    public bool Remove(TValue item) { return _Container.Remove(Indexed.Create(-1, item)); }

    public int Count {
        get { return _Container.Count; }
    }
    public bool IsReadOnly {
        get { return false; }
    }
}

একটি পরীক্ষা ক্লাস

[Fact]
public void ShouldWorkWithSuperSortedSet()
{
    // Sort points according to X
    var set = new SuperSortedSet<Point2D>
        (new System.Linq.Comparer<Point2D>((p0, p1) => p0.X.CompareTo(p1.X)));

    set.Add(new Point2D(9,10));
    set.Add(new Point2D(1,25));
    set.Add(new Point2D(11,-10));
    set.Add(new Point2D(2,99));
    set.Add(new Point2D(5,55));
    set.Add(new Point2D(5,23));
    set.Add(new Point2D(11,11));
    set.Add(new Point2D(21,12));
    set.Add(new Point2D(-1,76));
    set.Add(new Point2D(16,21));

    var xs = set.Select(p=>p.X).ToList();
    xs.Should().BeInAscendingOrder();
    xs.Count.Should()
       .Be(10);
    xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,5,9,11,11,16,21});

    set.Remove(new Point2D(5,55));
    xs = set.Select(p=>p.X).ToList();
    xs.Count.Should()
       .Be(9);
    xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,9,11,11,16,21});

    set.Remove(new Point2D(5,23));
    xs = set.Select(p=>p.X).ToList();
    xs.Count.Should()
       .Be(8);
    xs.ShouldBeEquivalentTo(new[]{-1,1,2,9,11,11,16,21});

    set.Contains(new Point2D(11, 11))
       .Should()
       .BeTrue();

    set.Contains(new Point2D(-1, 76))
        .Should().BeTrue();

    // Note that the custom compartor function ignores the Y value
    set.Contains(new Point2D(-1, 66))
        .Should().BeTrue();

    set.Contains(new Point2D(27, 66))
        .Should().BeFalse();

}

ট্যাগিং স্ট্রাক্ট

public struct Indexed<T>
{
    public int Index { get; private set; }
    public T Value { get; private set; }
    public Indexed(int index, T value) : this()
    {
        Index = index;
        Value = value;
    }

    public override string ToString()
    {
        return "(Indexed: " + Index + ", " + Value.ToString () + " )";
    }
}

public class Indexed
{
    public static Indexed<T> Create<T>(int indexed, T value)
    {
        return new Indexed<T>(indexed, value);
    }
}

ল্যাম্বদা তুলক সহায়ক

public class Comparer<T> : IComparer<T>
{
    private readonly Func<T, T, int> _comparer;

    public Comparer(Func<T, T, int> comparer)
    {
        if (comparer == null)
            throw new ArgumentNullException("comparer");
        _comparer = comparer;
    }

    public int Compare(T x, T y)
    {
        return _comparer(x, y);
    }
}

1

সমস্যাটি হ'ল আপনি এমন কীটি কী হিসাবে ব্যবহার করেন যা কী নয় (কারণ এটি একাধিকবার ঘটে)।

সুতরাং আপনার যদি সত্যিকারের স্থানাঙ্ক থাকে তবে আপনার সম্ভবত Pointআপনার সাজানো তালিকার কী হিসাবে নেওয়া উচিত ।

অথবা আপনি এমন একটি তৈরি করেন List<List<Header>>যেখানে আপনার প্রথম তালিকার সূচীটি এক্স-পজিশন এবং অভ্যন্তরীণ তালিকা সূচকটি y- পজিশন (বা তার বিপরীতে যদি আপনি চান তবে) সংজ্ঞায়িত করে।


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

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

1

এর মূল (শুল্কযুক্ত) কীটি একটি IComparableভিত্তিক শ্রেণি তৈরি করা যা সাম্যতা এবং হ্যাশিং বজায় রাখে, তবে কখনও সমান না হলে 0 এর সাথে তুলনা করে না। এটি করা যেতে পারে এবং কয়েকটি বোনাস দিয়ে তৈরি করা যায় - স্থিতিশীল বাছাই (এটি, বাছাই তালিকায় যুক্ত মানগুলি তাদের অবস্থান বজায় রাখবে), এবং ToString()কেবল আসল কী স্ট্রিংয়ের মানটি ফিরিয়ে দিতে পারে।

এই কৌশলটি এখানে করা উচিত যা কৌশলটি করা উচিত:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace System
{
    /// <summary>
    /// Defined in Totlsoft.Util.
    /// A key that will always be unique but compares
    /// primarily on the Key property, which is not required
    /// to be unique.
    /// </summary>
    public struct StableKey : IComparable<StableKey>, IComparable
    {
        private static long s_Next;
        private long m_Sequence;
        private IComparable m_Key;

        /// <summary>
        /// Defined in Totlsoft.Util.
        /// Constructs a StableKey with the given IComparable key.
        /// </summary>
        /// <param name="key"></param>
        public StableKey( IComparable key )
        {
            if( null == key )
                throw new ArgumentNullException( "key" );

            m_Sequence = Interlocked.Increment( ref s_Next );
            m_Key = key;
        }

        /// <summary>
        /// Overridden. True only if internal sequence and the
        /// Key are equal.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals( object obj )
        {
            if( !( obj is StableKey ) )
                return false;

            var dk = (StableKey)obj;

            return m_Sequence.Equals( dk.m_Sequence ) &&
                Key.Equals( dk.Key );
        }

        /// <summary>
        /// Overridden. Gets the hash code of the internal
        /// sequence and the Key.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return m_Sequence.GetHashCode() ^ Key.GetHashCode();
        }

        /// <summary>
        /// Overridden. Returns Key.ToString().
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Key.ToString();
        }

        /// <summary>
        /// The key that will be compared on.
        /// </summary>
        public IComparable Key
        {
            get
            {
                if( null == m_Key )
                    return 0;

                return m_Key;
            }
        }

        #region IComparable<StableKey> Members

        /// <summary>
        /// Compares this Key property to another. If they
        /// are the same, compares the incremented value.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo( StableKey other )
        {
            var cmp = Key.CompareTo( other.Key );
            if( cmp == 0 )
                cmp = m_Sequence.CompareTo( other.m_Sequence );

            return cmp;
        }

        #endregion

        #region IComparable Members

        int IComparable.CompareTo( object obj )
        {
            return CompareTo( (StableKey)obj );
        }

        #endregion
    }
}

এটি একটি দুর্দান্ত ধারণা। আমি ধারণাটি একটি কাস্টম আইকোল্লেশনে মুড়িয়েছি। দেখুন stackoverflow.com/a/21625939/158285
bradgonesurfing

0

লিনক.লুকআপ দুর্দান্ত এবং সব কিছু, তবে যদি আপনার টার্গেটটি হ'ল "কীগুলি" থেকে ডুপ্লিকেট করার সুযোগ দেয় তবে আপনি এই কাঠামোটি ব্যবহার করতে পারেন:

List<KeyValuePair<String, String>> FieldPatterns = new List<KeyValuePair<string, string>>() {
   new KeyValuePair<String,String>("Address","CommonString"),
   new KeyValuePair<String,String>("Username","UsernamePattern"),
   new KeyValuePair<String,String>("Username","CommonString"),
};

তারপরে আপনি লিখতে পারেন:

foreach (KeyValuePair<String,String> item in FieldPatterns)
{
   //use item.Key and item.Value
}

এইচটিএইচ


0

কৌশলটি হ'ল একটি অনন্য কী দিয়ে আপনার অবজেক্টটি বাড়ানো। নিম্নলিখিত পরীক্ষা দেখুন যা পাস। আমি আমার পয়েন্টগুলি তাদের X মান অনুসারে বাছাই করতে চাই। আমার তুলনা ফাংশনে কেবল একটি নগ্ন পয়েন্ট 2 ডি ব্যবহারের ফলে একই এক্স মানযুক্ত পয়েন্টগুলি মুছে ফেলা হবে। সুতরাং আমি পয়েন্ট 2 ডি ইনডেক্সড নামে একটি ট্যাগিং ক্লাসে মোড়ানো করি।

[Fact]
public void ShouldBeAbleToUseCustomComparatorWithSortedSet()
{
    // Create comparer that compares on X value but when X
    // X values are uses the index
    var comparer = new 
        System.Linq.Comparer<Indexed<Point2D>>(( p0, p1 ) =>
        {
            var r = p0.Value.X.CompareTo(p1.Value.X);
            return r == 0 ? p0.Index.CompareTo(p1.Index) : r;
        });

    // Sort points according to X
    var set = new SortedSet<Indexed<Point2D>>(comparer);

    int i=0;

    // Create a helper function to wrap each point in a unique index
    Action<Point2D> index = p =>
    {
        var ip = Indexed.Create(i++, p);
        set.Add(ip);
    };

    index(new Point2D(9,10));
    index(new Point2D(1,25));
    index(new Point2D(11,-10));
    index(new Point2D(2,99));
    index(new Point2D(5,55));
    index(new Point2D(5,23));
    index(new Point2D(11,11));
    index(new Point2D(21,12));
    index(new Point2D(-1,76));
    index(new Point2D(16,21));
    set.Count.Should()
       .Be(10);
    var xs = set.Select(p=>p.Value.X).ToList();
    xs.Should()
      .BeInAscendingOrder();
    xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,5,9,11,11,16,21});

}

এই কাজটি করার জন্য ইউটিলিটিগুলি

একটি তুলক যা ল্যাম্বডা নেয়

public class Comparer<T> : IComparer<T>
{
    private readonly Func<T, T, int> _comparer;

    public Comparer(Func<T, T, int> comparer)
    {
        if (comparer == null)
            throw new ArgumentNullException("comparer");
        _comparer = comparer;
    }

    public int Compare(T x, T y)
    {
        return _comparer(x, y);
    }
}

একটি ট্যাগিং স্ট্রাক্ট

public struct Indexed<T>
{
    public int Index { get; private set; }
    public T Value { get; private set; }
    public Indexed(int index, T value) : this()
    {
        Index = index;
        Value = value;
    }

    public override string ToString()
    {
        return "(Indexed: " + Index + ", " + Value.ToString () + " )";
    }
}

public class Indexed
{
    public static Indexed<T> Create<T>(int indexed, T value)
    {
        return new Indexed<T>(indexed, value);
    }
}

উপরোক্ত ধারণাগুলি সম্পূর্ণ কাস্টম আইকোলিকেশন ক্লাসে মোড়ানোর জন্য আমার অন্য উত্তরটি দেখুন
ব্র্যাডগোনসার্ফিং

0

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

public class ConcurrentOrderedList<Titem, Tsort> : ICollection<Titem>
{
    private object _lock = new object();
    private SortedDictionary<Tsort, List<Titem>> _internalLists;
    Func<Titem, Tsort> _getSortValue;
    
    public ConcurrentOrderedList(Func<Titem,Tsort> getSortValue)
    {
        _getSortValue = getSortValue;
        _internalLists = new SortedDictionary<Tsort, List<Titem>>();            
    }

    public int Count { get; private set; }

    public bool IsReadOnly => false;

    public void Add(Titem item)
    {
        lock (_lock)
        {
            List<Titem> values;
            Tsort sortVal = _getSortValue(item);
            if (!_internalLists.TryGetValue(sortVal, out values))
            {
                values = new List<Titem>();
                _internalLists.Add(sortVal, values);
            }
            values.Add(item);
            Count++;
        }            
    }

    public bool Remove(Titem item)
    {
        lock (_lock)
        {
            List<Titem> values;
            Tsort sortVal = _getSortValue(item);
            if (!_internalLists.TryGetValue(sortVal, out values))
                return false;

            var removed = values.Remove(item);
            if (removed)
                Count--;
            return removed;
        }
    }

    public void Clear()
    {
        lock (_lock)
        {
            _internalLists.Clear();
        }
    }

    public bool Contains(Titem item)
    {
        lock (_lock)
        {
            List<Titem> values;
            Tsort sortVal = _getSortValue(item);
            if (!_internalLists.TryGetValue(sortVal, out values))
                return false;
            return values.Contains(item);
        }
    }

    public void CopyTo(Titem[] array, int arrayIndex)
    {
        int i = arrayIndex;
        lock (_lock)
        {
            foreach (var list in _internalLists.Values)
            {
                list.CopyTo(array, i);
                i += list.Count;
            }
        }
    }

    public IEnumerator<Titem> GetEnumerator()
    {
        foreach (var list in _internalLists.Values)
        {
            foreach (var item in list)
                yield return item;
        }
    }

    public int IndexOf(Titem item)
    {
        int i = 0;
        var sortVal = _getSortValue(item);
        lock (_lock)
        {               
            foreach (var list in _internalLists)
            {
                if (object.Equals(list.Key, sortVal))
                {
                    int intIndex = list.Value.IndexOf(item);
                    if (intIndex == -1)
                        return -1;
                    return i + intIndex;
                }
                i += list.Value.Count;
            }
            return -1;
        }           
    }

    public void Insert(int index, Titem item)
    {
        throw new NotSupportedException();
    }

    // Note this method is indeterminate if there are multiple
    // items in the same sort position!
    public void RemoveAt(int index)
    {
        int i = 0;
        lock (_lock)
        {
            foreach (var list in _internalLists.Values)
            {
                if (i + list.Count < index)
                {
                    i += list.Count;
                    continue;
                }
                else
                {
                    list.RemoveAt(index - i);
                    return;
                }
            }
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

-1

একটি ক্লাস তৈরি করুন এবং তালিকাটি জিজ্ঞাসা করুন:

Public Class SortingAlgorithm
{
    public int ID {get; set;}
    public string name {get; set;}
    public string address1 {get; set;}
    public string city {get; set;}
    public string state {get; set;}
    public int age {get; set;}
}

//declare a sorting algorithm list
List<SortingAlgorithm> sortAlg = new List<SortingAlgorithm>();

//Add multiple values to the list
sortAlg.Add( new SortingAlgorithm() {ID = ID, name = name, address1 = address1, city = city, state = state, age = age});
sortAlg.Add( new SortingAlgorithm() {ID = ID, name = name, address1 = address1, city = city, state = state, age = age});
sortAlg.Add( new SortingAlgorithm() {ID = ID, name = name, address1 = address1, city = city, state = state, age = age});

//query and order by the list
  var sortedlist = (from s in sortAlg
                    select new { s.ID, s.name, s.address1, s.city, s.state, s.age })
                                                     .OrderBy(r => r.ID)
                                                     .ThenBy(r=> r.name)
                                                     .ThenBy(r=> r.city)
                                                     .ThenBy(r=>r.state)
                                                     .ThenBy(r=>r.age);

-1

এই আমার গ্রহণ এখানে। সচেতন হন, এখানে ড্রাগন হতে পারে, সি # এখনও আমার জন্য বেশ নতুন।

  • সদৃশ কীগুলি অনুমোদিত, তালিকাতে মান সংরক্ষণ করা হয়
  • আমি এটি একটি বাছাই করা কিউ হিসাবে ব্যবহার করেছি, তাই নাম এবং পদ্ধতি

ব্যবহার:

SortedQueue<MyClass> queue = new SortedQueue<MyClass>();
// new list on key "0" is created and item added
queue.Enqueue(0, first);
// new list on key "1" is created and item added
queue.Enqueue(1, second);
// items is added into list on key "0"
queue.Enqueue(0, third);
// takes the first item from list with smallest key
MyClass myClass = queue.Dequeue();
class SortedQueue<T> {
  public int Count;
  public SortedList<int, List<T>> Queue;

  public SortedQueue() {
    Count = 0;
    Queue = new SortedList<int, List<T>>();
  }

  public void Enqueue(int key, T value) {
    List<T> values;
    if (!Queue.TryGetValue(key, out values)){
      values = new List<T>();
      Queue.Add(key, values);
      Count += 1;
    }
    values.Add(value);
  }

  public T Dequeue() {
    if (Queue.Count > 0) {
      List<T> smallest = Queue.Values[0];
      if (smallest.Count > 0) {
        T item = smallest[0];
        smallest.Remove(item);
        return item;
      } else {
        Queue.RemoveAt(0);
        Count -= 1;
        return Dequeue();
      }
    }
    return default(T);
  }
}

বিসিএলে ইতিমধ্যে একটি শ্রেণি Queueরয়েছে, যা আইটেমগুলির প্রথম-ইন, প্রথম-আউট সংগ্রহ উপস্থাপন করে। আপনার ক্লাসের শব্দার্থবিজ্ঞান আলাদা। আপনার শ্রেণীর একটি সূচনা আছে (যেখানে আইটেমগুলির সজ্জা রয়েছে) তবে শেষ নেই (কোনও আইটেম কোথাও sertedোকানো যাবে)। সুতরাং Enqueueআপনার ক্লাসের পদ্ধতিটি অর্থহীন আইএমএইচও।
থিওডর জৌলিয়াস

@ থিডোরজৌলিয়াস ইয়ুপ, নামকরণ এখানে কিছুটা শোধ করা উচিত তবে আমি দৃly়তার সাথে মনে করি এটি ডাউন ডাউনের প্রাপ্য, এটির ওপির প্রয়োজনীয়তা রয়েছে এবং এটি কেবল ইনপুট / আউটপুট পদ্ধতির নাম পরিবর্তন এবং পুনর্নির্মাণের বিষয়। কেন এটিকে বলা হয়? আমার এমন কাঠামো দরকার যা আমি শুরু থেকে কিছুক্ষণের মধ্যে ফাঁকা রাখতে পারি এবং অগ্রাধিকার মানের ভিত্তিতে নতুন আইটেম যুক্ত করতে পারি। তাই PriorityQueueআরও উপযুক্ত নাম হবে।
একক

ওপি একটি বাছাইযোগ্য সংগ্রহ চায় যা ডুপ্লিকেট কীগুলিকে অনুমতি দেয়। আপনার শ্রেণি সংগ্রহ নয় , কারণ এটি গণনা করা যায় না। আমি জনসাধারণের ক্ষেত্রের ব্যবহারও অপছন্দ করি। ডাউনভোটগুলি ব্যক্তিগতভাবে নেবেন না। আপনি একক আপভোট ( -2 * 5 == +10) দিয়ে 5 টি ডাউনভোটের সুনাম ক্ষতি ক্ষতি করতে পারেন , সুতরাং এটি কোনও বড় কথা নয়। :-)
থিওডর জোলিয়াস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.