我正在对元素列表进行排序:
var matchEle = listOfElements.Where(e => e.Properties().Any(p => p.Name.Contains("Key", Asking for IEqualityComparer))).First();
Run Code Online (Sandbox Code Playgroud)
我习惯于直接使用 StringComparer、OrdinalIgnoreCase 或 CurrentCultureIgnoreCase,但是在这种情况下调用 Contains() 时,它会要求使用 IEqualityComparer。我想是因为数据结构/级别。我看到了如何设置 IEqualityComparer 的示例,例如
strEqualityComparer = new IEqualityComparer();
Run Code Online (Sandbox Code Playgroud)
并为 strEqualityComparer 定义类,但我不确定除此之外。有人可以帮助我让 linq 语句处理忽略案例吗?
更新:我很清楚这是数据结构的示例:
listOfElements = [element1, element2, etc..]
element1.Properties = ["Prop1", "Key1", "Prop2", "Key2", etc.]
Run Code Online (Sandbox Code Playgroud)
如果其任何属性具有包含关键字的值,我需要提取通过过滤器的元素,在本例中为“Key”,因此它不能是 .Equals 或 IndexOf。
命名空间中的IEqualityComparerSystem.Collections.Generic具有以下方法:
bool Equals(T x, T y);
int GetHashCode(T obj);
Run Code Online (Sandbox Code Playgroud)
由于此接口用于检查对象的相等性,因此第一种方法Equals是有意义的.但为什么我们也需要实施GetHashCode呢?为什么它首先存在于界面中?什么时候需要,为什么?
我在命名空间中使用它和Enumerable.Distinct()方法System.Linq,我很惊讶地发现它甚至GetHashCode()被调用了Equals().为什么?Distinct工作怎么样?
我正在阅读源代码,EqualityComparer<T>.Default发现它并不那么聪明.这是一个例子:
enum MyEnum : int { A, B }
EqualityComparer<MyEnum>.Default.Equals(MyEnum.A, MyEnum.B)
//is as fast as
EqualityComparer<int>.Default.Equals(0, 1)
enum AnotherEnum : long { A = 1L, B = 2L }
//is 8x slower than
EqualityComparer<long>.Default.Equals(1L, 2L)
Run Code Online (Sandbox Code Playgroud)
原因很明显来自EqualityComparer中私有方法的源代码.
private static EqualityComparer<T> CreateComparer()
{
//non-important codes are ignored
if (c.IsEnum && (Enum.GetUnderlyingType(c) == typeof(int)))
{
return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(EnumEqualityComparer<int>), c);
}
return new ObjectEqualityComparer<T>();
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到EqualityComparer<int>.Default,EqualityComparer<MyEnum>.Default并EqualityComparer<long>.Default得到一个明智的比较器,其Equals方法如下:
public static bool Equals(int x, int y) …Run Code Online (Sandbox Code Playgroud) 我已经阅读过这篇文章,但它没有回答我的问题.
MSDN 说:
我们建议您从EqualityComparer(Of T)类派生而不是实现IEqualityComparer(Of T)接口,因为EqualityComparer(Of T)类使用IEquatable(Of T).Equals方法而不是Object来测试相等性.等于方法.
但如果我看一下实现,他们都使用泛型类型:
public class AAA:IEqualityComparer<Box>
{
public bool Equals(Box x, Box y)
{
}
public int GetHashCode(Box obj)
{
}
}
public class BBB : EqualityComparer<Box>
{
public override bool Equals(Box x, Box y)
{
}
public override int GetHashCode(Box obj)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
尝试遵循文档,我无法使其工作.使用键字符串键入KeyedCollection.
如何在KeyedCollection中使字符串键不区分大小写?
在Dictionary上只能在ctor中传递StringComparer.OrdinalIgnoreCase.
private static WordDefKeyed wordDefKeyed = new WordDefKeyed(StringComparer.OrdinalIgnoreCase); // this fails
public class WordDefKeyed : KeyedCollection<string, WordDef>
{
// The parameterless constructor of the base class creates a
// KeyedCollection with an internal dictionary. For this code
// example, no other constructors are exposed.
//
public WordDefKeyed() : base() { }
public WordDefKeyed(IEqualityComparer<string> comparer)
: base(comparer)
{
// what do I do here???????
}
// This is the only method that absolutely must be overridden,
// because without …Run Code Online (Sandbox Code Playgroud) 我已经困惑了几天......随意拍下我的任何假设.
我们正在使用带整数键的字典.我假设在这种情况下密钥的值直接用作哈希.这是否意味着(如果密钥分组在一个小范围内)密钥哈希的分布(与密钥本身相同,对吗?)将处于类似的小范围内,因此哈希表的选择不好?
是否更好的是提供一个IEqualityComparer,用素数和模数学做一些聪明的东西来计算更好的分布式哈希?
这个问题类似于这里的问题.
我们都知道PointF是什么,不是吗?这是数据结构:
public struct PointF
{
public float X;
public float Y;
}
Run Code Online (Sandbox Code Playgroud)
如何实施IEqualityComparer<PointF>宽容?假设我的Equals代码是这样的
public const float Epsilon = 0.01; //say
public bool Equals(PointF pt1, PointF pt2)
{
return Math.Abs(pt1.X-pt2.X)<Epsilon && Math.Abs(pt1.Y-pt2.Y)<Epsilon;
}
Run Code Online (Sandbox Code Playgroud)
问题:如何实现正确的,GetHashCode以便对于字典PointF,我会正确访问元素?
我几天头脑裂开但仍然无法找到满意的解决方案.
我可以为以下比较器逻辑编写哈希码函数吗?
My如果来自(A,B,C)的至少两个属性匹配,则两个实例相等.
Equals部分很简单,但是我对哈希码部分感到困惑,我的一部分认为它可能是不可能的.
class MyOtherComparer : IEqualityComparer<My>
{
public bool Equals(My x, My y)
{
if (Object.ReferenceEquals(x, y))
return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
int matches = 0;
if(x.A == y.A) matches++;
if(x.B == y.B) matches++;
if(x.C == y.C) matches++;
// match on two out of three
return (matches > 1)
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int …Run Code Online (Sandbox Code Playgroud) 我有许多是从类派生的类BaseClass,其中BaseClass仅仅有一个'ID属性.
我现在需要对其中一些对象的集合进行区分.我为每个子类反复提供以下代码:
public class PositionComparer : IEqualityComparer<Position>
{
public bool Equals(Position x, Position y)
{
return (x.Id == y.Id);
}
public int GetHashCode(Position obj)
{
return obj.Id.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于逻辑只是基于Id,我想创建一个单一的比较器来减少重复:
public class BaseClassComparer : IEqualityComparer<BaseClass>
{
public bool Equals(BaseClass x, BaseClass y)
{
return (x.Id == y.Id);
}
public int GetHashCode(BaseClass obj)
{
return obj.Id.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
但这似乎没有编译:
IEnumerable<Position> positions = GetAllPositions();
positions = allPositions.Distinct(new BaseClassComparer())
Run Code Online (Sandbox Code Playgroud)
...因为它说它无法转换BaseClass为Position.为什么比较器会强制执行此Distinct()调用的返回值?
在我的应用程序的一部分中,我有一个选项可以显示当前艺术家不在音乐库中的专辑列表。为此,我调用音乐 API 来获取该艺术家的所有专辑列表,然后删除当前库中的专辑。
为了处理名称的不同大小写以及标题中丢失(或额外标点符号)的可能性,我写了一个IEqualityComparer在.Except调用中使用:
var missingAlbums = allAbumns.Except(ownedAlbums, new NameComparer());
Run Code Online (Sandbox Code Playgroud)
这是Equals方法:
public bool Equals(string x, string y)
{
// Check whether the compared objects reference the same data.
if (ReferenceEquals(x, y)) return true;
// Check whether any of the compared objects is null.
if (x is null || y is null)
return false;
return string.Compare(x, y, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) == 0;
}
Run Code Online (Sandbox Code Playgroud)
这是GetHashCode方法:
public int GetHashCode(string obj)
{
// Check whether …Run Code Online (Sandbox Code Playgroud)