কিভাবে হ্যাশসেট <টি> থেকে প্রকৃত আইটেমটি পুনরুদ্ধার করবেন?


86

কেন এটি সম্ভব নয় তা নিয়ে আমি এই প্রশ্নটি পড়েছি , তবে সমস্যার কোনও সমাধান পাইনি।

আমি একটি নেট থেকে একটি আইটেম পুনরুদ্ধার করতে চাই HashSet<T>। আমি এমন একটি পদ্ধতির সন্ধান করছি যাতে এই স্বাক্ষর থাকবে:

/// <summary>
/// Determines if this set contains an item equal to <paramref name="item"/>, 
/// according to the comparison mechanism that was used when the set was created. 
/// The set is not changed. If the set does contain an item equal to 
/// <paramref name="item"/>, then the item from the set is returned.
/// </summary>
bool TryGetItem<T>(T item, out T foundItem);

এই জাতীয় পদ্ধতিতে কোনও আইটেমের জন্য সেট অনুসন্ধান করা হবে ও (1)। একটি থেকে কোনও আইটেম পুনরুদ্ধারের একমাত্র উপায় HashSet<T>হ'ল সমস্ত আইটেমগুলি গণনা করা যা হে (এন)।

আমার নিজের তৈরি HashSet<T>বা এটিকে ব্যবহার করে অন্য কোনও সমস্যার জন্য আমি কোনও মতবিরোধ খুঁজে পাইনি Dictionary<K, V>। অন্য কোন ধারণা?

দ্রষ্টব্য:
আমি HashSet<T>আইটেমটি আছে কিনা তা পরীক্ষা করতে চাই না । আমি সংরক্ষিত আইটেমটির রেফারেন্স পেতে চাই HashSet<T>কারণ আমার এটি আপডেট করতে হবে (এটি অন্য কোনও উদাহরণের মাধ্যমে প্রতিস্থাপন না করে)। আমি যে আইটেমটিতে যাব তা TryGetItemসমান হবে (তুলনামূলক পদ্ধতিটি যা আমি কনস্ট্রাক্টরের কাছে দিয়েছি) তবে এটি একই রেফারেন্স হবে না।


4
ইনপুট হিসাবে আপনি যে আইটেমটি পাস করেছেন সেগুলি কেন ব্যবহার করে এবং ফেরত দেবে না?
ম্যাথিয়াস


4
আপনি যদি একটি কী মান উপর ভিত্তি করে একটি বস্তু সন্ধান করার প্রয়োজন হয়, তাহলে তখন অভিধান <টি> এটা সঞ্চয় করতে আরো উপযুক্ত সংগ্রহ করা যেতে পারে।
ThatBlairGuy

@ থ্যাটব্লেয়ারগুই: আপনি ঠিক বলেছেন। আমি মনে করি আমি আমার আইটেমগুলি সংরক্ষণের জন্য অভ্যন্তরীণভাবে একটি অভিধান ব্যবহার করে নিজের সেট সংগ্রহটি বাস্তবায়ন করব। কীটি হ'ল আইটেমের হ্যাশকোড। আমার প্রায়শই হ্যাশসেটের মতো পারফরম্যান্স থাকবে এবং আমার সংগ্রহ থেকে কোনও আইটেম যুক্ত / অপসারণ করতে / প্রতিবার দরকার হলে এটি একটি কী সরবরাহ করতে সক্ষম হবে save
ফ্রাঙ্কোইস সি

4
@ মথিয়াস কারণ হ্যাশসেটে এমন কোনও আইটেম থাকতে পারে যা ইনপুটটির সমান হয়, তবে আসলে এটি একই নয়। উদাহরণস্বরূপ আপনার রেফারেন্স প্রকারের একটি হ্যাশসেট থাকতে পারে তবে আপনি সামগ্রীর তুলনা করতে চান, সমতার জন্য উল্লেখটি নয়।
NounVerber

উত্তর:


28

আপনি যা জিজ্ঞাসা করছেন তা এক বছর আগে .NET কোরে যুক্ত হয়েছিল এবং সম্প্রতি নেট নেট 7.7.২ এ যুক্ত হয়েছিল :

নেট ফ্রেমওয়ার্ক ৪.7.২ এ আমরা মানক সংগ্রহের ধরণগুলিতে কয়েকটি এপিআই যুক্ত করেছি যা নীচে নতুন কার্যকারিতা সক্ষম করবে।
- অন্যান্য সংগ্রহের ধরণে ব্যবহৃত ট্রাই প্যাটার্নটি মেলানোর জন্য 'ট্রাইগেটভ্যালু' সোর্টার্ড এবং হ্যাশসেটে যুক্ত করা হয়।

স্বাক্ষরটি নিম্নরূপ (নেট নেট 4.7.2 এবং এর উপরে পাওয়া গেছে):

    //
    // Summary:
    //     Searches the set for a given value and returns the equal value it finds, if any.
    //
    // Parameters:
    //   equalValue:
    //     The value to search for.
    //
    //   actualValue:
    //     The value from the set that the search found, or the default value of T when
    //     the search yielded no match.
    //
    // Returns:
    //     A value indicating whether the search was successful.
    public bool TryGetValue(T equalValue, out T actualValue);

PS : আপনি যদি আগ্রহী হন তবে ভবিষ্যতে তারা যুক্ত করছেন এমন সম্পর্কিত ফাংশন রয়েছে - হ্যাশসেট.গেটঅরএড (টি)।


65

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

তৃতীয় পক্ষের লাইব্রেরি ব্যতীত Dictionary<T, T>মানগুলির অনুরূপ কীগুলির সাথে ব্যবহার করা সবচেয়ে ভাল কাজ , যেহেতু অভিধানটি হ্যাশ টেবিল হিসাবে তার এন্ট্রিগুলি সঞ্চয় করে। পারফরম্যান্স-ভিত্তিতে এটি হ্যাশসেটের সমান, তবে এটি অবশ্যই স্মৃতিশক্তি নষ্ট করে (প্রতি প্রবেশের পয়েন্টারের আকার)।

Dictionary<T, T> myHashedCollection;
...
if(myHashedCollection.ContainsKey[item])
    item = myHashedCollection[item]; //replace duplicate
else
    myHashedCollection.Add(item, item); //add previously unknown item
...
//work with unique item

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

4
যেহেতু কীটি মূল্যের মধ্যে সঞ্চিত থাকে আমি অভিধানের পরিবর্তে কেয়েডক্লিকেশন থেকে উত্তরাধিকার সূত্রে সংগ্রহটি ব্যবহার করার পরামর্শ দিই। msdn.microsoft.com/en-us/library/ms132438(v=vs.110).aspx
অ্যাক্সেস অস্বীকার

11

এই পদ্ধতিটি .NET ফ্রেমওয়ার্ক 4.7.2 (এবং এর আগে। নেট কোর 2.0 ) এ যুক্ত করা হয়েছে; দেখতে HashSet<T>.TryGetValueউত্স উদ্ধৃত :

/// <summary>
/// Searches the set for a given value and returns the equal value it finds, if any.
/// </summary>
/// <param name="equalValue">The value to search for.
/// </param>
/// <param name="actualValue">
/// The value from the set that the search found, or the default value
/// of <typeparamref name="T"/> when the search yielded no match.</param>
/// <returns>A value indicating whether the search was successful.</returns>
/// <remarks>
/// This can be useful when you want to reuse a previously stored reference instead of 
/// a newly constructed one (so that more sharing of references can occur) or to look up
/// a value that has more complete data than the value you currently have, although their
/// comparer functions indicate they are equal.
/// </remarks>
public bool TryGetValue(T equalValue, out T actualValue)

4
পাশাপাশি সাজানোসেটের জন্যও।
নওফাল

4

স্ট্রিং সমতা তুলনামূলক বেশি বোঝা সম্পর্কে কী:

  class StringEqualityComparer : IEqualityComparer<String>
{
    public string val1;
    public bool Equals(String s1, String s2)
    {
        if (!s1.Equals(s2)) return false;
        val1 = s1;
        return true;
    }

    public int GetHashCode(String s)
    {
        return s.GetHashCode();
    }
}
public static class HashSetExtension
{
    public static bool TryGetValue(this HashSet<string> hs, string value, out string valout)
    {
        if (hs.Contains(value))
        {
            valout=(hs.Comparer as StringEqualityComparer).val1;
            return true;
        }
        else
        {
            valout = null;
            return false;
        }
    }
}

এবং তারপরে হ্যাশসেটটি ঘোষণা করুন:

HashSet<string> hs = new HashSet<string>(new StringEqualityComparer());

এগুলি মেমরি পরিচালনার বিষয়ে - অভিন্ন কপির পরিবর্তে হ্যাশसेटে থাকা আসল আইটেমটি ফিরিয়ে দেওয়া returning সুতরাং উপরের কোডে আমরা একই বিষয়বস্তু সহ স্ট্রিংটি খুঁজে পাই এবং তারপরে এটিতে একটি রেফারেন্স ফিরিয়ে দেব। স্ট্রিংগুলির জন্য এটি ইন্টার্নিংয়ের মতো একটি।
mp666

@ জুমালাইফগার্ড @ এমপি 666 এটি যেমনটি কাজ করার গ্যারান্টিযুক্ত নয়। HashSetসুনির্দিষ্ট মান রূপান্তর সরবরাহ করার জন্য এটির জন্য কেউ ইনস্ট্যান্ট করছে । একটি অনুকূল সমাধান TryGetValueবিশেষায়িতদের একটি নতুন ইভেন্টে পাস করার জন্য হবে StringEqualityComparer(অন্যথায় as StringEqualityComparerএটি .val1সম্পত্তি নিক্ষেপের ফলে নালায় পরিণত হতে পারে )। এটি করার মাধ্যমে, স্ট্রিংএকুয়েলিটি কম্পিউটারটি হ্যাশসেট এক্সটেনশনের মধ্যে নেস্টেড ব্যক্তিগত শ্রেণিতে পরিণত হতে পারে। ফিউথার, ওভাররাইড হওয়া সমতা তুলনাকারীর ক্ষেত্রে, স্ট্রিংএকুয়ালিটি কম্পিউটারকে ডিফল্টর মধ্যে কল করা উচিত।
গ্রিম উইকসটেড

HashSet <স্ট্রিং> valueCash = নতুন HashSet <স্ট্রিং> (নতুন StringEqualityComparer ()): আপনি আপনার HashSet ডিক্লেয়ার প্রয়োজন
mp666

4
ডার্টি হ্যাক আমি জানি এটি কীভাবে কাজ করে তবে এর অলসতা এটিকে কেবল এক ধরণের সমাধান হিসাবে কাজ করে
এমকাজেম আখগারি

2

ঠিক আছে, সুতরাং আপনি এটি এটি করতে পারেন

YourObject x = yourHashSet.Where(w => w.Name.Contains("strin")).FirstOrDefault();

এটি নির্বাচিত বস্তুর একটি নতুন ইনস্ট্যান্স পাওয়ার জন্য। আপনার অবজেক্ট আপডেট করার জন্য, তারপরে আপনার ব্যবহার করা উচিত:

yourHashSet.Where(w => w.Name.Contains("strin")).FirstOrDefault().MyProperty = "something";

এটি একটি আকর্ষণীয় উপায়, কেবলমাত্র আপনাকে দ্বিতীয় বার চেষ্টা করে মুড়িয়ে ফেলা দরকার - যাতে আপনি তালিকায় নেই এমন কোনও কিছু সন্ধান করলে আপনি একটি নালরফেরেন্সইপেক্টেশন পাবেন। কিন্তু এটি সঠিক দিকের একটি পদক্ষেপ?
পাইটর কুলা

11
লিনিকিউ সংগ্রহটি পূর্ববর্তী লুপে, অর্থাৎ ও (এন) দেখার সময়কে ট্র্যাভার করে। যদিও এটি সমস্যার সমাধান, এটি প্রথমে হ্যাশসেট ব্যবহারের উদ্দেশ্যকে হারাতে পারে।
নিক্লাস একমান


2

InternalIndexOfহ্যাশসেটের অভ্যন্তরীণ ফাংশনটি অ্যাক্সেস করে অন্য একটি ট্রিক প্রতিবিম্ব করবে । মাঠের নামগুলি হার্ডকোডযুক্ত মনে রাখবেন, সুতরাং আসন্ন .NET সংস্করণগুলিতে যদি সেগুলি পরিবর্তন হয় তবে এটি ভঙ্গ হবে।

নোট: আপনি মনো ব্যবহার করেন, তাহলে আপনার কাছ থেকে ক্ষেত্র নাম পরিবর্তন করা উচিত m_slotsকাছে _slots

internal static class HashSetExtensions<T>
{
    public delegate bool GetValue(HashSet<T> source, T equalValue, out T actualValue);

    public static GetValue TryGetValue { get; }

    static HashSetExtensions() {
        var targetExp = Expression.Parameter(typeof(HashSet<T>), "target");
        var itemExp   = Expression.Parameter(typeof(T), "item");
        var actualValueExp = Expression.Parameter(typeof(T).MakeByRefType(), "actualValueExp");

        var indexVar = Expression.Variable(typeof(int), "index");
        // ReSharper disable once AssignNullToNotNullAttribute
        var indexExp = Expression.Call(targetExp, typeof(HashSet<T>).GetMethod("InternalIndexOf", BindingFlags.NonPublic | BindingFlags.Instance), itemExp);

        var truePart = Expression.Block(
            Expression.Assign(
                actualValueExp, Expression.Field(
                    Expression.ArrayAccess(
                        // ReSharper disable once AssignNullToNotNullAttribute
                        Expression.Field(targetExp, typeof(HashSet<T>).GetField("m_slots", BindingFlags.NonPublic | BindingFlags.Instance)), indexVar),
                    "value")),
            Expression.Constant(true));

        var falsePart = Expression.Constant(false);

        var block = Expression.Block(
            new[] { indexVar },
            Expression.Assign(indexVar, indexExp),
            Expression.Condition(
                Expression.GreaterThanOrEqual(indexVar, Expression.Constant(0)),
                truePart,
                falsePart));

        TryGetValue = Expression.Lambda<GetValue>(block, targetExp, itemExp, actualValueExp).Compile();
    }
}

public static class Extensions
{
    public static bool TryGetValue2<T>(this HashSet<T> source, T equalValue,  out T actualValue) {
        if (source.Count > 0) {
            if (HashSetExtensions<T>.TryGetValue(source, equalValue, out actualValue)) {
                return true;
            }
        }
        actualValue = default;
        return false;
    }
}

পরীক্ষা:

var x = new HashSet<int> { 1, 2, 3 };
if (x.TryGetValue2(1, out var value)) {
    Console.WriteLine(value);
}

1

सॉোর্টসেটের সম্ভবত সেই পরিস্থিতিতে ও (লগ এন) দেখার সময় থাকতে পারে, যদি এটি কোনও বিকল্প ব্যবহার করে। এখনও ও (1) নয়, তবে কমপক্ষে আরও ভাল।


1

@ এমপি 6 answer6 উত্তরের পরিবর্তিত বাস্তবায়ন যাতে এটি কোনও ধরণের হ্যাশসেটের জন্য ব্যবহার করা যায় এবং ডিফল্ট সমতা তুলনাকারীকে ওভাররাইড করার অনুমতি দেয়।

public interface IRetainingComparer<T> : IEqualityComparer<T>
{
    T Key { get; }
    void ClearKeyCache();
}

/// <summary>
/// An <see cref="IEqualityComparer{T}"/> that retains the last key that successfully passed <see cref="IEqualityComparer{T}.Equals(T,T)"/>.
/// This class relies on the fact that <see cref="HashSet{T}"/> calls the <see cref="IEqualityComparer{T}.Equals(T,T)"/> with the first parameter
/// being an existing element and the second parameter being the one passed to the initiating call to <see cref="HashSet{T}"/> (eg. <see cref="HashSet{T}.Contains(T)"/>).
/// </summary>
/// <typeparam name="T">The type of object being compared.</typeparam>
/// <remarks>This class is thread-safe but may should not be used with any sort of parallel access (PLINQ).</remarks>
public class RetainingEqualityComparerObject<T> : IRetainingComparer<T> where T : class
{
    private readonly IEqualityComparer<T> _comparer;

    [ThreadStatic]
    private static WeakReference<T> _retained;

    public RetainingEqualityComparerObject(IEqualityComparer<T> comparer)
    {
        _comparer = comparer;
    }

    /// <summary>
    /// The retained instance on side 'a' of the <see cref="Equals"/> call which successfully met the equality requirement agains side 'b'.
    /// </summary>
    /// <remarks>Uses a <see cref="WeakReference{T}"/> so unintended memory leaks are not encountered.</remarks>
    public T Key
    {
        get
        {
            T retained;
            return _retained == null ? null : _retained.TryGetTarget(out retained) ? retained : null;
        }
    }


    /// <summary>
    /// Sets the retained <see cref="Key"/> to the default value.
    /// </summary>
    /// <remarks>This should be called prior to performing an operation that calls <see cref="Equals"/>.</remarks>
    public void ClearKeyCache()
    {
        _retained = _retained ?? new WeakReference<T>(null);
        _retained.SetTarget(null);
    }

    /// <summary>
    /// Test two objects of type <see cref="T"/> for equality retaining the object if successful.
    /// </summary>
    /// <param name="a">An instance of <see cref="T"/>.</param>
    /// <param name="b">A second instance of <see cref="T"/> to compare against <paramref name="a"/>.</param>
    /// <returns>True if <paramref name="a"/> and <paramref name="b"/> are equal, false otherwise.</returns>
    public bool Equals(T a, T b)
    {
        if (!_comparer.Equals(a, b))
        {
            return false;
        }

        _retained = _retained ?? new WeakReference<T>(null);
        _retained.SetTarget(a);
        return true;
    }

    /// <summary>
    /// Gets the hash code value of an instance of <see cref="T"/>.
    /// </summary>
    /// <param name="o">The instance of <see cref="T"/> to obtain a hash code from.</param>
    /// <returns>The hash code value from <paramref name="o"/>.</returns>
    public int GetHashCode(T o)
    {
        return _comparer.GetHashCode(o);
    }
}

/// <summary>
/// An <see cref="IEqualityComparer{T}"/> that retains the last key that successfully passed <see cref="IEqualityComparer{T}.Equals(T,T)"/>.
/// This class relies on the fact that <see cref="HashSet{T}"/> calls the <see cref="IEqualityComparer{T}.Equals(T,T)"/> with the first parameter
/// being an existing element and the second parameter being the one passed to the initiating call to <see cref="HashSet{T}"/> (eg. <see cref="HashSet{T}.Contains(T)"/>).
/// </summary>
/// <typeparam name="T">The type of object being compared.</typeparam>
/// <remarks>This class is thread-safe but may should not be used with any sort of parallel access (PLINQ).</remarks>
public class RetainingEqualityComparerStruct<T> : IRetainingComparer<T> where T : struct 
{
    private readonly IEqualityComparer<T> _comparer;

    [ThreadStatic]
    private static T _retained;

    public RetainingEqualityComparerStruct(IEqualityComparer<T> comparer)
    {
        _comparer = comparer;
    }

    /// <summary>
    /// The retained instance on side 'a' of the <see cref="Equals"/> call which successfully met the equality requirement agains side 'b'.
    /// </summary>
    public T Key => _retained;


    /// <summary>
    /// Sets the retained <see cref="Key"/> to the default value.
    /// </summary>
    /// <remarks>This should be called prior to performing an operation that calls <see cref="Equals"/>.</remarks>
    public void ClearKeyCache()
    {
        _retained = default(T);
    }

    /// <summary>
    /// Test two objects of type <see cref="T"/> for equality retaining the object if successful.
    /// </summary>
    /// <param name="a">An instance of <see cref="T"/>.</param>
    /// <param name="b">A second instance of <see cref="T"/> to compare against <paramref name="a"/>.</param>
    /// <returns>True if <paramref name="a"/> and <paramref name="b"/> are equal, false otherwise.</returns>
    public bool Equals(T a, T b)
    {
        if (!_comparer.Equals(a, b))
        {
            return false;
        }

        _retained = a;
        return true;
    }

    /// <summary>
    /// Gets the hash code value of an instance of <see cref="T"/>.
    /// </summary>
    /// <param name="o">The instance of <see cref="T"/> to obtain a hash code from.</param>
    /// <returns>The hash code value from <paramref name="o"/>.</returns>
    public int GetHashCode(T o)
    {
        return _comparer.GetHashCode(o);
    }
}

/// <summary>
/// Provides TryGetValue{T} functionality similar to that of <see cref="IDictionary{TKey,TValue}"/>'s implementation.
/// </summary>
public class ExtendedHashSet<T> : HashSet<T>
{
    /// <summary>
    /// This class is guaranteed to wrap the <see cref="IEqualityComparer{T}"/> with one of the <see cref="IRetainingComparer{T}"/>
    /// implementations so this property gives convenient access to the interfaced comparer.
    /// </summary>
    private IRetainingComparer<T> RetainingComparer => (IRetainingComparer<T>)Comparer;

    /// <summary>
    /// Creates either a <see cref="RetainingEqualityComparerStruct{T}"/> or <see cref="RetainingEqualityComparerObject{T}"/>
    /// depending on if <see cref="T"/> is a reference type or a value type.
    /// </summary>
    /// <param name="comparer">(optional) The <see cref="IEqualityComparer{T}"/> to wrap. This will be set to <see cref="EqualityComparer{T}.Default"/> if none provided.</param>
    /// <returns>An instance of <see cref="IRetainingComparer{T}"/>.</returns>
    private static IRetainingComparer<T> Create(IEqualityComparer<T> comparer = null)
    {
        return (IRetainingComparer<T>) (typeof(T).IsValueType ? 
            Activator.CreateInstance(typeof(RetainingEqualityComparerStruct<>)
                .MakeGenericType(typeof(T)), comparer ?? EqualityComparer<T>.Default)
            :
            Activator.CreateInstance(typeof(RetainingEqualityComparerObject<>)
                .MakeGenericType(typeof(T)), comparer ?? EqualityComparer<T>.Default));
    }

    public ExtendedHashSet() : base(Create())
    {
    }

    public ExtendedHashSet(IEqualityComparer<T> comparer) : base(Create(comparer))
    {
    }

    public ExtendedHashSet(IEnumerable<T> collection) : base(collection, Create())
    {
    }

    public ExtendedHashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer) : base(collection, Create(comparer))
    {
    }

    /// <summary>
    /// Attempts to find a key in the <see cref="HashSet{T}"/> and, if found, places the instance in <paramref name="original"/>.
    /// </summary>
    /// <param name="value">The key used to search the <see cref="HashSet{T}"/>.</param>
    /// <param name="original">
    /// The matched instance from the <see cref="HashSet{T}"/> which is not neccessarily the same as <paramref name="value"/>.
    /// This will be set to null for reference types or default(T) for value types when no match found.
    /// </param>
    /// <returns>True if a key in the <see cref="HashSet{T}"/> matched <paramref name="value"/>, False if no match found.</returns>
    public bool TryGetValue(T value, out T original)
    {
        var comparer = RetainingComparer;
        comparer.ClearKeyCache();

        if (Contains(value))
        {
            original = comparer.Key;
            return true;
        }

        original = default(T);
        return false;
    }
}

public static class HashSetExtensions
{
    /// <summary>
    /// Attempts to find a key in the <see cref="HashSet{T}"/> and, if found, places the instance in <paramref name="original"/>.
    /// </summary>
    /// <param name="hashSet">The instance of <see cref="HashSet{T}"/> extended.</param>
    /// <param name="value">The key used to search the <see cref="HashSet{T}"/>.</param>
    /// <param name="original">
    /// The matched instance from the <see cref="HashSet{T}"/> which is not neccessarily the same as <paramref name="value"/>.
    /// This will be set to null for reference types or default(T) for value types when no match found.
    /// </param>
    /// <returns>True if a key in the <see cref="HashSet{T}"/> matched <paramref name="value"/>, False if no match found.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="hashSet"/> is null.</exception>
    /// <exception cref="ArgumentException">
    /// If <paramref name="hashSet"/> does not have a <see cref="HashSet{T}.Comparer"/> of type <see cref="IRetainingComparer{T}"/>.
    /// </exception>
    public static bool TryGetValue<T>(this HashSet<T> hashSet, T value, out T original)
    {
        if (hashSet == null)
        {
            throw new ArgumentNullException(nameof(hashSet));
        }

        if (hashSet.Comparer.GetType().IsInstanceOfType(typeof(IRetainingComparer<T>)))
        {
            throw new ArgumentException($"HashSet must have an equality comparer of type '{nameof(IRetainingComparer<T>)}' to use this functionality", nameof(hashSet));
        }

        var comparer = (IRetainingComparer<T>)hashSet.Comparer;
        comparer.ClearKeyCache();

        if (hashSet.Contains(value))
        {
            original = comparer.Key;
            return true;
        }

        original = default(T);
        return false;
    }
}

4
যেহেতু আপনি লিনক এক্সটেনশন পদ্ধতি ব্যবহার করছেন Enumerable.Contains, এটি সেটের সমস্ত উপাদানকে গণনা করবে এবং সেগুলির তুলনা করবে, সেটটির হ্যাশ বাস্তবায়নের যে কোনও সুবিধা হারাবে losing তারপরে আপনি সম্ভবত কেবল লিখতে পারেন set.SingleOrDefault(e => set.Comparer.Equals(e, obj)), যা আপনার সমাধান হিসাবে একই আচরণ এবং কর্মক্ষমতা বৈশিষ্ট্য রয়েছে।
ড্যানিয়েল এএ পেলসেমেকার

@ ভার্টলিংক ভাল ধরা - আপনি একদম ঠিক বলেছেন। আমি আমার উত্তরটি পরিবর্তন করব।
গ্রিম উইক্টেড

যাইহোক, আপনি যদি কোনও হ্যাশসেটটি আবদ্ধ করতে চান যা অভ্যন্তরীণভাবে আপনার তুলনাকারী ব্যবহার করে work এটির
ড্যানিয়েল এএ পেলসেমেকার

@ ভার্টলিঙ্ক আপনাকে ধন্যবাদ! আমি হ্যাশসেটকে একটি বিকল্প হিসাবে মোড়ানো শেষ করেছি তবে তুলনামূলক এবং অতিরিক্ত বহুমুখীতার জন্য একটি এক্সটেনশন পদ্ধতি সরবরাহ করছি। এটি এখন থ্রেড-নিরাপদ এবং মেমরি ফাঁস করবে না ... তবে এটি আমার প্রত্যাশার চেয়ে কিছুটা বেশি কোড!
গ্রিম উইক্টেড

@ ফ্র্যাঙ্কোইস উপরের কোডটি লেখার জন্য একটি "অনুকূল" সময় / মেমরি সমাধান আবিষ্কার করার অনুশীলন ছিল; তবে, আমি আপনাকে এই পদ্ধতিটি অনুসরণ করার পরামর্শ দিচ্ছি না। একটি কাস্টম আইকোয়ালিটি কম্পিউটারের সাথে একটি অভিধান <টি, টি> ব্যবহার করা অনেক বেশি সোজা-ফরোয়ার্ড এবং ভবিষ্যত-প্রমাণ!
গ্রিম উইক্টেড

-2

হ্যাশসেটের একটি কন্টেনস (টি) পদ্ধতি রয়েছে।

আপনার যদি একটি কাস্টম তুলনা পদ্ধতি প্রয়োজন (যেমন, কোনও ব্যক্তির বস্তু সঞ্চয় করুন তবে সমতা তুলনার জন্য এসএসএন ব্যবহার করুন) প্রয়োজন হলে আপনি একটি আইক্যুয়ালিটি কম্পিউটারটি নির্দিষ্ট করতে পারেন ।


-11

আপনি টোললিস্ট () পদ্ধতিটিও ব্যবহার করতে পারেন এবং এটিতে একটি সূচক প্রয়োগ করতে পারেন।

HashSet<string> mySet = new HashSet();
mySet.Add("mykey");
string key = mySet.toList()[0];

আমি নিশ্চিত নই যে আপনি যখন এই যুক্তিটি কাজ করেছিলেন তখন কেন আপনি ভোট পেয়েছিলেন। অভিধানের <স্ট্রিং, আইসেট <স্ট্রিং>> দিয়ে শুরু হওয়া একটি কাঠামো থেকে আমাকে মানগুলি বের করতে হবে যেখানে ইসেটে x সংখ্যার মান রয়েছে। এই মানগুলি প্রাপ্ত করার সর্বাধিক প্রত্যক্ষ উপায় হ'ল অভিধানটি কী এবং ইসেট মানটি টান দিয়ে লুপ করা। তারপরে আমি স্বতন্ত্র মানগুলি প্রদর্শন করতে ISet এর মধ্য দিয়ে লুপ করেছি। এটি মার্জিত নয়, তবে এটি কাজ করেছে।
j.hul 8'19
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.