C# 改进重复检查方法
早上好,伙计们 使用C sharp.net4和MS Visual Studio 2010 我已经为我的windows窗体程序开发了一个复制检查器。 当我的数据网格上有几百条记录时,它工作得非常完美,几乎是即时的 我注意到的问题是,当显示6000条记录时,效率根本不够,需要几分钟的时间 我想知道是否有人有一些好的技巧可以让这个方法更快,或者是改进现有的设计,或者是一个不同的方法,我已经看过了 再次感谢您的帮助 代码如下:C# 改进重复检查方法,c#,.net,winforms,datagridview,duplicates,C#,.net,Winforms,Datagridview,Duplicates,早上好,伙计们 使用C sharp.net4和MS Visual Studio 2010 我已经为我的windows窗体程序开发了一个复制检查器。 当我的数据网格上有几百条记录时,它工作得非常完美,几乎是即时的 我注意到的问题是,当显示6000条记录时,效率根本不够,需要几分钟的时间 我想知道是否有人有一些好的技巧可以让这个方法更快,或者是改进现有的设计,或者是一个不同的方法,我已经看过了 再次感谢您的帮助 代码如下: public void CheckForDuplicate() {
public void CheckForDuplicate()
{
DataGridViewRowCollection coll = ParetoGrid.Rows;
DataGridViewRowCollection colls = ParetoGrid.Rows;
IList<String> listParts = new List<String>();
int count = 0;
foreach (DataGridViewRow item in coll)
{
foreach (DataGridViewRow items in colls)
{
count++;
if ((items.Cells["NewPareto"].Value != null) && (items.Cells["NewPareto"].Value != DBNull.Value))
{
if ((items.Cells["NewPareto"].Value != DBNull.Value) && (items.Cells["NewPareto"].Value != null) && (items.Cells["NewPareto"].Value.Equals(item.Cells["NewPareto"].Value)))
{
if ((items.Cells["Part"].Value != DBNull.Value) && (items.Cells["Part"].Value != null) && !(items.Cells["Part"].Value.Equals(item.Cells["Part"].Value)))
{
listParts.Add(items.Cells["Part"].Value.ToString());
dupi = true; //boolean toggle
}
}
}
}
}
MyErrorGrid.DataSource = listParts.Select(x => new { Part = x }).ToList();
}
public void CheckForDuplicate()
{
DataGridViewRowCollection coll=ParetoGrid.Rows;
DataGridViewRowCollection colls=ParetoGrid.Rows;
IList listParts=新列表();
整数计数=0;
foreach(coll中的DataGridViewRow项)
{
foreach(colls中的DataGridViewRow项)
{
计数++;
if((items.Cells[“NewPareto”].Value!=null)和&(items.Cells[“NewPareto”].Value!=DBNull.Value))
{
if((items.Cells[“NewPareto”].Value!=DBNull.Value)&&(items.Cells[“NewPareto”].Value!=null)&&(items.Cells[“NewPareto”].Value.Equals(item.Cells[“NewPareto”].Value)))
{
if((items.Cells[“Part”].Value!=DBNull.Value)&&&(items.Cells[“Part”].Value!=null)&&&!(items.Cells[“Part”].Value.Equals(item.Cells[“Part”].Value)))
{
添加(items.Cells[“Part”].Value.ToString());
dupi=true;//布尔切换
}
}
}
}
}
MyErrorGrid.DataSource=listParts.Select(x=>new{Part=x}).ToList();
}
任何问题都会让我知道,我会尽力回答。有一种方法可以让这更有效。您需要计算每个项目的哈希值。具有不同散列的项不可能是重复项
一旦你有了散列,你可以通过散列进行排序,或者使用一个具有有效键控检索的数据结构(如
字典)来查找所有的重复项。如果可以,你应该尝试在基础数据上而不是在UI对象上这样做-但是我有一种预感,你是从一组数据行中播种数据,在这种情况下,您可能无法做到这一点
我认为这里的问题很大一部分是重复按名称取消对单元格的引用,以及重复遵从第二组单元格的事实。因此,请提前做好准备:
var first = (from row in coll.Cast<DataGridViewRow>()
let newpareto = row.Cells["NewPareto"].Value ?? DBNull.Value
let part = row.Cells["Part"].Value ?? DBNull.Value
where newpareto != DBNull.Value && part != DBNull.Value
select new
{ newpareto = newpareto, part = part }).ToArray();
//identical - so a copy-paste job (if not using anonymous type we could refactor)
var second = (from row in colls.Cast<DataGridViewRow>()
let newpareto = row.Cells["NewPareto"].Value ?? DBNull.Value
let part = row.Cells["Part"].Value ?? DBNull.Value
where newpareto != DBNull.Value && part != DBNull.Value
select new
{ newpareto = newpareto, part = part }).ToArray();
//now produce our list of strings
var listParts = (from f in first
where second.Any(v => v.newpareto.Equals(f.newpareto)
&& !v.part.Equals(f.part))
select f.part.ToString()).ToList(); //if you want it as a list.
var first=(从coll.Cast()中的行开始)
设newpareto=row.Cells[“newpareto”].Value??DBNull.Value
let part=行.单元格[“part”].Value??DBNull.Value
其中newpareto!=DBNull.Value&&part!=DBNull.Value
选择新的
{newpareto=newpareto,part=part}).ToArray();
//相同-因此是复制粘贴作业(如果不使用匿名类型,我们可以重构)
var second=(从colls.Cast()中的行开始)
设newpareto=row.Cells[“newpareto”].Value??DBNull.Value
let part=行.单元格[“part”].Value??DBNull.Value
其中newpareto!=DBNull.Value&&part!=DBNull.Value
选择新的
{newpareto=newpareto,part=part}).ToArray();
//现在产生我们的字符串列表
var listParts=(从第一个中的f开始)
其中second.Any(v=>v.newpareto.Equals(f.newpareto)
&&!v部分等于(f部分))
选择f.part.ToString()).ToList()//如果你想把它列为一个列表。
一个简单的优化,不会对代码造成太大的更改,不要查看所有列两次,外部循环循环所有列,内部循环从外部循环所在的位置循环到末尾。单元格[“NewPareto”]是字符串查找。如果你在循环外得到一个数字(表在循环中不会改变),然后通过数字访问呢?最初的原因是我循环得到第一个值,然后用它作为基础,我通过第二个循环检查所有其他值,看是否有匹配项。@StevenSmith如果你看了我的答案,我应该补充一点,我刚刚更改了它,以获得一个更好的解决方案,这意味着你每行只查找一次单元格。啊,我来看看,舒德缩短了我的时间!虽然我原则上同意,但这不是一个简单的解决方案:如何为单元格或DBNulls中的空值计算哈希?如果采用明显的方法并使用0
,则无法在此处的相等逻辑上实现短路,其中任何带有null
或DBNull.Value
的单元格都会被自动忽略。您将强制字典对这些行执行更长的相等性检查,因为它们将共享相同的哈希。@AndrasZoltan是的,此算法要求您对某些最终不同的项执行检查。这是它的基本属性。改进仍然很大,因为您不再需要进行6000*6000/2比较。使用哈希非常有趣,虽然我以前从未尝试过,但我对我在代码中实现它的技能有点怀疑这是另一个有趣的问题,同样-我最初错过了一个,直到Eren在我的第一个解决方案中指出它-这里的重复实际上是一个字段相等,另一个字段不相等-这不可能在单个哈希中实现。要匹配有问题的代码,这应该是&&!part1.Equals(part2)
好的,我做了一些测试,用我的版本做了3次,用你的版本做了3次。根据4832条记录,地雷需要1分21秒才能完成。你的需要57秒才能完成。这是一个好消息,因为它可以节省24秒的时间,但仍然需要改进。hehegona试试看,您的新解决方案看起来快多了!设newpareto=行[“newpareto”]。值??DBNull.Value无法将索引应用于