我是Linq的新手并且仍在努力熟悉它。我在linq查询下面找到了重复项,它的工作原理如下:
//“MergedName”是我正在查询并找到重复名称的数据列。
var duplicates = result.AsEnumerable()
`.Select(dr => dr.Field<string("MergedName").Replace("'", "''"))
.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
foreach (string duplicate in duplicates.ToArray())
{
// Logic to keep one and delete another duplicate.
}
现在,我想在同一列“MergedName”上找到相似的名称。 例如:John Smith和John Smith Jr. 我用.Where子句写了一些内容,但我的语法错误
var duplicates = result.AsEnumerable()
.Select(dr => dr.Field<string>("MergedName").Replace("'", "''"))
.Where(C => C.Field<string>("MergedName").ToLower().IndexOf(C.Field<string>("MergedName").ToLower().Trim()) != 1)
.Select(g => g.Key)
.ToList();
foreach (string duplicate in duplicates.ToArray())
{
// Logic to keep one and delete another duplicate.
}
错误:在Where语句中 - “字符串不包含'Field'的定义,并且最好的扩展方法重载'System.Data.DatarowExtensions.Field有一些无效的参数'。
你可以帮我解释一下这段代码吗?或者我可以使用contains找到相似名称的任何其他方式。
答案 0 :(得分:0)
如果没有发布原始集合的类型,很难说,但问题似乎正是您的错误消息中所述。
LINQ在迭代步骤中工作,在调用Select(dr => dr.Field<string>("MergedName").Replace("'", "''"))
后,您的下一个expresion适用于字符串集合。字符串类型
.Field
我想您可以尝试将where子句中的C.Field<string>("MergedName").ToLower()
简化为C.ToLower()
你也没有在你的第二个语句中进行任何分组,因此Select(g => g.Key)
不会工作,因为String类型上也没有Key属性。
这只解决了语法问题,你的Where子句看起来仍然很奇怪。您正在将每个字符串与自身进行比较。
您可以尝试类似
的内容var names = result.AsEnumerable()
.Select(dr => dr.Field<string("MergedName").Replace("'", "''").ToLower().Trim())
.ToList(); //ToList not necessary here, but could prevent multiple executions of the expresion
var duplicates = names.Where(n => names.Any(m => n.IndexOf(m) != -1)) //quadratic complexity
.ToList();
只要将自己的条件放入最后一个语句的任何部分,就会有两个字符串m
和n
,可以根据需要进行比较。
这绝对不是您问题的最佳性能解决方案,但它在您的任务中使用LINQ,并且易于编写和理解。
澄清后:
var enumerableResult = result.AsEnumerable();
var duplicates = enumerableResult.
.Where(dr => enumerableResult.Any(dr2 => /*your comparison*/)
.ToList();
比较可能是这样的:
dr.Field<string>("MergedName").Replace("'", "''").Trim().ToLower().IndexOf(dr2.Field<string>("MergedName").Replace("'", "''").Trim().ToLower()) != -1
此条件基于您问题中的条件,而不是评论中的条件。但你不需要使用这个内联sytax并可以调用一些自定义方法,所以它看起来像.Any(dr2 => AreSamePerson(dr, dr2))
这又有二次复杂性,只有当你有很多要比较的记录时才会出现问题。
现在您可以收集人物对象而不仅仅是字符串。请记住,您不能从原始集合中删除重复集合的成员,但需要一些相当复杂的逻辑。
所以最好的解决方案似乎是:
var duplicates = result.AsEnumerable()
.GroupBy(x => x, new PersonyComparer() )
.Where(g => g.Count() > 1)
class PersonyComparer : IEqualityComparer<Person>//person is the type of objects that are in starting collection
{
public bool Equals(Person b1, Person b2)
{
if (b2 == null && b1 == null)
return true;
else if (b1 == null | b2 == null)
return false;
if(/*your condition*/)
return true;
else
return false;
}
public int GetHashCode(Person bx)
{
return 0; //you must make sure that objects that are equal have same hashcode
}
}
这可能会导致问题,因此请确保您的相等函数是对称的(如果a == b然后b == a)和传递(如果a == b和b == c则a == c)。否则你的灌浆可能会被搞砸了。
然后你可以遍历重复集合的对象
foreach(var pgroup in duplicates)
{
foreach(var person in pgroup .Skip(1))
{
//remove from original collection
}
}
答案 1 :(得分:0)
让我举例告诉你为什么你不应该这样做。正如Noxor所说,一种可行的方法是使用IEqualityComparer
。但现在的问题是:什么是平等的?你的&#34;包含平等&#34;引入了一种你无法解决的模糊性。
让我以最基本的方式解释这一点,忘记案例和字符串替换。看到这个小的Linqpad程序:
void Main()
{
var dt = new DataTable();
dt.Columns.Add("MergedName", typeof(string));
dt.Rows.Add("Abby Kelley Foster");
dt.Rows.Add("Kelley Foster");
dt.Rows.Add("Abby Kelley");
dt.AsEnumerable()
.Select(r => r.Field<string>("MergedName"))
.GroupBy(s => s, new SubstringComparer())
.Select(g => new { g.Key, Count = g.Count() })
.Dump();
}
public class SubstringComparer : IEqualityComparer<string>
{
public bool Equals(string left, string right)
{
return left.Contains(right) || right.Contains(left);
}
public int GetHashCode(string value)
{
return 0; // Just return 0; There is no hashing mechanism implemented that gives "Abby Kelley Foster" and "Abby Kelley" the same hashcode.
}
}
输出是什么?右:
Abby Kelley Foster 3
但是现在让我们改变数据行的顺序:
dt.Rows.Add("Abby Kelley");
dt.Rows.Add("Kelley Foster");
dt.Rows.Add("Abby Kelley Foster");
你能扣除输出吗?这是:
Abby Kelley 1
Kelley Foster 2
Abby Kelley Foster发生了什么事?
比较者首先遇到了两个第一个不等的行,Abby Kelley算了一个,继续比较Kelley Foster和Abby Kelley Foster:宾果游戏! &#34;等&#34 ;.但是,此时它永远不会返回到第一行以将其与第三行进行比较。
你可以尝试一种比较所有行的更复杂(但仍然很简单)的算法,但是你会得到
Abby Kelley Foster 3
还是错的。只有Abby Kelley和Abby Kelley Foster是同一个人。 Kelley Foster完全是另一个人。换句话说:您无法通过任何自动算法解决此问题。只有精确的等式才能通过简单的算法确定。
用一个人为的例子来打这个家:假设一个条目只是&#34; Jr。&#34;。现在所有的名字都带有&#34; Jr。&#34;将被视为重复!