如何从HashSet <T>中检索实际项目?

Fra*_*s C 77 .net c# hashset

我已经读过这个问题,为什么它不可能,但没有找到问题的解决方案.

我想从.NET中检索一个项目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);
Run Code Online (Sandbox Code Playgroud)

使用这种方法搜索集合的项目将是O(1).从a中检索项目的唯一方法HashSet<T>是枚举所有O(n)项.

除了自己制作HashSet<T>或使用之外,我还没有找到解决这个问题的方法Dictionary<K, V>.还有其他想法吗?

注意:
我不想检查是否HashSet<T>包含该项目.我想获得对存储在项目中的项的引用,HashSet<T>因为我需要更新它(不用另一个实例替换它).我将传递给它的项目TryGetItem将是相等的(根据我传递给构造函数的比较机制)但它不会是相同的引用.

小智 64

这实际上是集合中的一个巨大遗漏.您只需要一个Keys of Dictionary或一个允许检索对象引用的HashSet.很多人都要求它,为什么它没有得到修复是超出我的.

如果没有第三方库,最好的解决方法是使用Dictionary<T, T>与值相同的键,因为Dictionary将其条目存储为哈希表.性能方面它与HashSet相同,但它当然浪费了内存(每个条目的指针大小).

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
Run Code Online (Sandbox Code Playgroud)

  • 由于键存储在值中,我建议使用从 KeyedCollection 继承的集合而不是字典。https://msdn.microsoft.com/en-us/library/ms132438(v=vs.110).aspx (2认同)

Evd*_*afa 17

您要求的是一年前添加到.NET Core,最近添加到.NET 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);
Run Code Online (Sandbox Code Playgroud)

签名如下(在.NET 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);
Run Code Online (Sandbox Code Playgroud)

PS.:如果您感兴趣,他们将来会添加相关功能 --HashSet.GetOrAdd(T).


Dou*_*las 11

此方法已添加到.NET Framework 4.7.2(以及之前的.NET Core 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)
Run Code Online (Sandbox Code Playgroud)


mp6*_*666 5

如何重载字符串相等比较器:

  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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将HashSet声明为:

HashSet<string> hs = new HashSet<string>(new StringEqualityComparer());
Run Code Online (Sandbox Code Playgroud)