C# 如何通过自定义子字符串等式仅迭代不同的字符串值
和问题类似,我尝试只迭代给定字符串的子字符串的不同值,例如:C# 如何通过自定义子字符串等式仅迭代不同的字符串值,c#,linq,iequalitycomparer,C#,Linq,Iequalitycomparer,和问题类似,我尝试只迭代给定字符串的子字符串的不同值,例如: List<string> keys = new List<string>() { "foo_boo_1", "foo_boo_2, "foo_boo_3, "boo_boo_1" } public int GetHashCode(string obj) { var index = obj.LastIndexOf("_"); return obj.Substrin
List<string> keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2,
"foo_boo_3,
"boo_boo_1"
}
public int GetHashCode(string obj)
{
var index = obj.LastIndexOf("_");
return obj.Substring(0, index).GetHashCode();
}
var keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2",
"foo_boo_3",
"boo_boo_1"
};
var distinct = keys
.Select(k => new
{
original = k,
truncated = k.Contains("_") ? k.Substring(0, k.LastIndexOf("_")) : k
})
.GroupBy(k => k.truncated)
.Select(g => g.First().original);
但结果是:
福布斯1福布斯2
福布斯3
boo_boo_1 使用
IEqualityComparer
如何删除子字符串的不同值(foo\u boo\u 2
和foo\u boo\u 3
)?
*请注意,“真实”键要长得多,类似于“1_0_8-B153_GF_6_2”,因此我必须使用LastIndexOf 等式比较器中的
GetHashCode
方法返回整个字符串的哈希代码,只需对子字符串进行哈希,例如:
List<string> keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2,
"foo_boo_3,
"boo_boo_1"
}
public int GetHashCode(string obj)
{
var index = obj.LastIndexOf("_");
return obj.Substring(0, index).GetHashCode();
}
var keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2",
"foo_boo_3",
"boo_boo_1"
};
var distinct = keys
.Select(k => new
{
original = k,
truncated = k.Contains("_") ? k.Substring(0, k.LastIndexOf("_")) : k
})
.GroupBy(k => k.truncated)
.Select(g => g.First().original);
您当前的实现存在一些缺陷:
Equals
和GetHashCode
都不能抛出异常(必须检查null
)Equals
为x
和y
返回true
,则GetHashCode(x)==GetHashCode(y)
。反例是“abc_1”
和“abc_2”
Distinct
返回不正确的结果(Distinct
第一个计算哈希)
正确的代码可以是这样的
public class MyEqualityComparer : IEqualityComparer<string> {
public bool Equals(string x, string y) {
if (ReferenceEquals(x, y))
return true;
else if ((null == x) || (null == y))
return false;
int xIndex = x.LastIndexOf('_');
int yIndex = y.LastIndexOf('_');
if (xIndex >= 0)
return (yIndex >= 0)
? x.Substring(0, xIndex) == y.Substring(0, yIndex)
: false;
else if (yIndex >= 0)
return false;
else
return x == y;
}
public int GetHashCode(string obj) {
if (null == obj)
return 0;
int index = obj.LastIndexOf('_');
return index < 0
? obj.GetHashCode()
: obj.Substring(0, index).GetHashCode();
}
}
要获得更简洁的解决方案,避免使用自定义的
IEqualityComparer
,您可以使用GroupBy
。例如:
List<string> keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2,
"foo_boo_3,
"boo_boo_1"
}
public int GetHashCode(string obj)
{
var index = obj.LastIndexOf("_");
return obj.Substring(0, index).GetHashCode();
}
var keys = new List<string>()
{
"foo_boo_1",
"foo_boo_2",
"foo_boo_3",
"boo_boo_1"
};
var distinct = keys
.Select(k => new
{
original = k,
truncated = k.Contains("_") ? k.Substring(0, k.LastIndexOf("_")) : k
})
.GroupBy(k => k.truncated)
.Select(g => g.First().original);
var keys=new List()
{
“foo_boo_1”,
“foo_boo_2”,
“foo_boo_3”,
“boo_boo_1”
};
var distinct=键
.选择(k=>new
{
原始=k,
截断=k.Contains(“\u”)?k.Substring(0,k.LastIndexOf(“\u”):k
})
.GroupBy(k=>k.截断)
.选择(g=>g.First().original);
这将产生:
福布斯1
boo_boo_1
嘿@DavidG,谢谢,
等于(…)
?我可以将其保留为NotImplementedException吗?Equals
方法甚至不会被调用,因为您的所有字符串都不同。进行此更改,它将是。当调用Equals时?你知道,你可以调试此代码并自己解决它,对吗?我已经尝试在Equals(…)
中设置断点,但它不会中断。当我将其设置为NotImplementedException
时,程序崩溃。只有当等于(…)
引用GetHashCode(…)
时,它才有效,谢谢。嘿@dmitry,回答得很好。你能解释一下为什么断点在Equals(…)
中没有中断吗?@Shahar Shokrani:Distinct
分两个阶段比较x
和y
:第一阶段比较散列;如果散列码不同,则不需要调用Equals
,只有当散列码相等时,它才会运行Equals
。我们的散列很好,看起来我们根本不需要等于,但是索引是-1呢