我已经读过这个问题,为什么它不可能,但没有找到问题的解决方案.
我想从.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)
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)
如何重载字符串相等比较器:
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)