我有两个员工名单,我想从中获得唯一的记录,但这有一个扭曲.每个列表中都有一个Employee类:
public class Employee
{
// I want to completely ignore ID in the comparison
public int ID{ get; set; }
// I want to use FirstName and LastName in comparison
public string FirstName{ get; set; }
public string LastName{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想要匹配的唯一属性是FirstName和LastName.我想在比较中完全忽略ID.allFulltimeEmployees列表中有3名员工,allParttimeEmployees列表中有3名员工.名单上的两个项目的名字和姓氏相匹配 - 莎莉琼斯和弗雷德杰克逊.列表中有一个项不匹配,因为FirstName是相同的,但LastName不同:
emp.id = null; // not populated or used in comparison
emp.FirstName = "Joe"; // same
emp.LastName = "Smith"; // different
allFulltimeEmployees.Add(emp);
emp.id = 3; // not used in comparison
emp.FirstName = "Joe"; // …Run Code Online (Sandbox Code Playgroud) 我正在实现一个可重用的DoubleEqualityComparer(具有自定义容差:"epsilon"构造函数参数),以简化LINQ的使用,使用double序列.例如:
bool myDoubleFound = doubles.Contains(myDouble, new DoubleEqualityComparer(epsilon: 0.01));
Run Code Online (Sandbox Code Playgroud)
实现GetHashCode的正确方法是什么?这是代码:
public class DoubleEqualityComparer : IEqualityComparer<double>, IEqualityComparer<double?>
{
private readonly double epsilon;
public DoubleEqualityComparer(double epsilon)
{
if (epsilon < 0)
{
throw new ArgumentException("epsilon can't be negative", "epsilon");
}
this.epsilon = epsilon;
}
public bool Equals(double x, double y)
{
return System.Math.Abs(x - y) < this.epsilon;
}
public int GetHashCode(double obj)
{
// ?
}
}
Run Code Online (Sandbox Code Playgroud)
PS:我总是可以返回相同的值(例如:GetHashCode(double obj){return 0;})以始终强制调用Equals(double,double)方法(不是很高效,我知道),但我记得这个当比较器与字典一起使用时,解决方案会导致问题...
我如何实现IEqualityComparer<DataRow>从DataTable下一个结构中删除重复行:
ID primary key, col_1, col_2, col_3, col_4
Run Code Online (Sandbox Code Playgroud)
默认比较器不起作用,因为每行都有自己唯一的主键.
如何实现IEqualityComparer<DataRow>将跳过主键并仅比较剩余的数据.
我有这样的事情:
public class DataRowComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
return
x.ItemArray.Except(new object[] { x[x.Table.PrimaryKey[0].ColumnName] }) ==
y.ItemArray.Except(new object[] { y[y.Table.PrimaryKey[0].ColumnName] });
}
public int GetHashCode(DataRow obj)
{
return obj.ToString().GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
和
public static DataTable RemoveDuplicates(this DataTable table)
{
return
(table.Rows.Count > 0) ?
table.AsEnumerable().Distinct(new DataRowComparer()).CopyToDataTable() :
table;
}
Run Code Online (Sandbox Code Playgroud)
但它只打电话GetHashCode()而不打电话Equals()
'Equal'和'GetHashcode'方法存在于对象类中,我们的类型继承了对象基类.直接实现对象的两个方法和使用IComparer接口有什么不同?
如果我们重写对象的Equal和GetHashCode,并推送到哈希表,它将使用overring的相等方法?
什么是新的哈希表与IEqualityComparer构造函数的不同之处?
首先我看到IEqualityComparer是匿名类型,那里的答案没有回答我的问题,因为显而易见的原因是我需要一个IEqualityComparer不IComparer用于Linq的Distinct()方法.我也检查了其他答案,这些都没有解决方案......
问题
我有一些代码来操纵和从中提取记录 DataTable
var glext = m_dtGLExt.AsEnumerable();
var cflist =
(from c in glext
orderby c.Field<string>(m_strpcCCType),
c.Field<string>(m_strpcCC),
c.Field<string>(m_strpcCCDesc),
c.Field<string>(m_strpcCostItem)
select new
{
CCType = c.Field<string>(m_strpcCCType),
CC = c.Field<string>(m_strpcCC),
CCDesc = c.Field<string>(m_strpcCCDesc),
CostItem = c.Field<string>(m_strpcCostItem)
}).Distinct();
Run Code Online (Sandbox Code Playgroud)
但是我需要使用不同的方法来区分大小写.这里扔我的是使用匿名类型.
尝试解决方案1
如果我有SomeClass具体的物体,我显然可以做到
public class SumObject
{
public string CCType { get; set; }
public string CC { get; set; }
public string CCDesc { get; set; }
public string CostItem { get; set; …Run Code Online (Sandbox Code Playgroud) TL; DR我正在寻找一种方式来获得IEqualityComparer<T>的IComparer<T>,无论哪个数据类型是T,包括在不区分大小写的选项T是string.或者我需要针对此问题的不同解决方案.
以下是完整的故事:我正在使用LFU策略实现简单的通用缓存.要求是必须能够选择缓存是区分大小写还是不区分大小写 - 如果string恰好是缓存键的数据类型(这不是必需的).在解决方案中,我主要开发缓存,我期望数百亿的缓存查找,以及最多100,000个条目的缓存大小.由于这些数字,我立即停止使用导致分配的任何字符串操作(例如.ToLower().GetHashCode()等),而是选择使用IComparer和IEqualityComparer,因为它们是标准的BCL功能.此缓存的用户可以将比较器传递给构造函数.以下是代码的相关片段:
public class LFUCache<TKey,TValue>
{
private readonly Dictionary<TKey,CacheItem> entries;
private readonly SortedSet<CacheItem> lfuList;
private class CacheItem
{
public TKey Key;
public TValue Value;
public int UseCount;
}
private class CacheItemComparer : IComparer<CacheItem>
{
private readonly IComparer<TKey> cacheKeyComparer;
public CacheItemComparer(IComparer<TKey> cacheKeyComparer)
{
this.cacheKeyComparer = cacheKeyComparer;
if (cacheKeyComparer == null)
this.cacheKeyComparer = Comparer<TKey>.Default;
}
public int Compare(CacheItem x, CacheItem y) …Run Code Online (Sandbox Code Playgroud) 泛型List<T>可以包含任何类型 - 值或引用。当检查列表是否包含对象时,.Contains()使用类型 T 的默认值EqualityComparer<T>并调用.Equals()(这是我的理解)。如果没有定义 EqualityComparer,则默认比较器将调用.Equals(). 默认情况下,.Equals()调用.ReferenceEquals(), so.Contains()仅当列表包含完全相同的对象时才返回 true。
直到您需要重写.Equals()以实现值相等,此时默认比较器表示如果两个对象具有相同的值,则它们是相同的。我想不出有哪一种情况适合引用类型。
我从 @Enigmativity 听到的是,实现IEqualityComparer<StagingDataRow>将为我键入的 DataRow 提供一个默认的相等比较器,该比较器将用于代替Object\xe2\x80\x93 的默认比较器,从而允许我在StagingDataRow.Equals().
问题:
\nEqualityComparer<StagingDataRow>.Equals()而不是调用StagingDataRow.Equals()?IEqualityComparer<StagingDataRow>.GetHashCode(StagingDataRow obj)哈希什么,它应该返回与 相同的值吗StagingDataRow.GetHashCode()?IEqualityComparer<StagingDataRow>.GetHashCode(StagingDataRow obj)?我正在寻找的对象还是列表中的对象?两个都?让实例方法接受自身作为参数会很奇怪......一般来说,在重写时如何区分值相等和引用相等.Equals()?
这是为两个词典的相等性创建比较器的最佳方法吗?这需要准确.请注意,Entity.Columns是KeyValuePair的字典(字符串,对象):
public class EntityColumnCompare : IEqualityComparer<Entity>
{
public bool Equals(Entity a, Entity b)
{
var aCol = a.Columns.OrderBy(KeyValuePair => KeyValuePair.Key);
var bCol = b.Columns.OrderBy(KeyValuePAir => KeyValuePAir.Key);
if (aCol.SequenceEqual(bCol))
return true;
else
return false;
}
public int GetHashCode(Entity obj)
{
return obj.Columns.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
对GetHashCode实现也不太确定.
谢谢!
这是目标代码:
public class DlpItem : IEqualityComparer<DlpItem>
{
public string Text { get; set; }
public int Id { get; set; }
public DlpItem(int pId)
{
Text = string.Empty;
Id = pId;
}
public override bool Equals(object obj)
{
return Id == (obj as DlpItem).Id;
}
public bool Equals(DlpItem a, DlpItem b)
{
return a.Id == b.Id;
}
public int GetHashCode(DlpItem item)
{
return Id.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个列表如下:
var list1 = new List<DlpItem>();
list1.Add(new DlpItem(1));
list1.Add(new DlpItem(2));
var list2 = new …Run Code Online (Sandbox Code Playgroud) 这是我刚刚写的相等比较器,因为我想从包含实体的列表中获得一组不同的项.
class InvoiceComparer : IEqualityComparer<Invoice>
{
public bool Equals(Invoice x, Invoice y)
{
// A
if (Object.ReferenceEquals(x, y)) return true;
// B
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false;
// C
return x.TxnID == y.TxnID;
}
public int GetHashCode(Invoice obj)
{
if (Object.ReferenceEquals(obj, null)) return 0;
return obj.TxnID2.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
Distinct需要比较器而不是Func<T,T,bool>?如果我想,我可以替换(C)
return GetHashCode(x) == GetHashCode(y)
c# ×8
linq ×4
.net ×3
generics ×2
iequatable ×2
collections ×1
comparison ×1
datatable ×1
dictionary ×1
double ×1
epsilon ×1
gethashcode ×1
hashcode ×1
hashtable ×1
icomparer ×1
list ×1
memorycache ×1