C# 在数据表中查找重复项,然后比较重复项

C# 在数据表中查找重复项,然后比较重复项,c#,linq,c#-4.0,.net-4.0,C#,Linq,C# 4.0,.net 4.0,我有一个数据表,它有重复的行。我需要获得副本,并在某些列中比较副本行以获得最佳值 DataTable dt = new DataTable(); dt.Rows.Add(1, "Test1", "584", 12); dt.Rows.Add(2, "Test2", "32", 123); dt.Rows.Add(3, "Test3", "425", 54); dt.Rows.Add(4, "Test1", "4", 755); dt.Rows.Add(5, "Test5", "854", 87

我有一个数据表,它有重复的行。我需要获得副本,并在某些列中比较副本行以获得最佳值

DataTable dt = new DataTable();

dt.Rows.Add(1, "Test1", "584", 12);
dt.Rows.Add(2, "Test2", "32", 123);
dt.Rows.Add(3, "Test3", "425", 54);
dt.Rows.Add(4, "Test1", "4", 755);
dt.Rows.Add(5, "Test5", "854", 879);
dt.Rows.Add(6, "Test2", "1", null);
dt.Rows.Add(7, "Test2", "999", 3);
注意,测试1和2有重复项

(1, "Test1", "584", 12)
(4, "Test1", "4", 755)

(2, "Test2", "32", 123)
(6, "Test2", "1", null)
(7, "Test2", "999", 3)
既然我有了副本。我需要做一行,有最好的价值。新数据表应显示:

Test1 = "Test1", "584", 755
Test2 = "Test2", "999", 123
Test3 = "Test3", "425", 54
Test5 = "Test5", "854", 879
//GroupBy(x=>x[1])=GroupBy第二列
//其中(x=>x.Count()>1)=仅获取计数大于1的组,因此重复
var duplicates=dt.Rows.OfType().GroupBy(x=>x[1]),其中(x=>x.Count()>1.ToList();
//列举所有重复项
foreach(var重复中的重复)
{
//枚举副本的每一行
foreach(var数据行一式两份)
{
//做点什么…
//我不知道你的规则为什么一行比另一行好,所以那部分你必须自己弄清楚,或者扩展你的问题
}
}
也许你正在寻找这个:

DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Text", typeof(string));
dt.Columns.Add("Value1", typeof(string));
dt.Columns.Add("Value2", typeof(int));

dt.Rows.Add(1, "Test1", "584", 12);
dt.Rows.Add(2, "Test2", "32", 123);
dt.Rows.Add(3, "Test3", "425", 54);
dt.Rows.Add(4, "Test1", "4", 755);
dt.Rows.Add(5, "Test5", "854", 879);
dt.Rows.Add(6, "Test2", "1", null);
dt.Rows.Add(7, "Test2", "999", 3);

var duplicates = dt.Rows.OfType<DataRow>().GroupBy(x => x[1]).Where(x => x.Count() > 1).ToList();

//get the current highestId (first column) so that when we remove duplicates and a new row the new row will get the next available id
var highestId = dt.Rows.OfType<DataRow>().Max(x => (int)x[0]);

//enumerate all duplicates
foreach (var duplicate in duplicates)
{
    //get the highest value of each column
    var newId = ++highestId;
    var newText = duplicate.Key;
    var newValue1 = duplicate.Max(x => x[2]); //this does a string comparison, instead of a numeric one, this means that for example that 2 is bigger then 10

    // use this if you need numeric comparison
    var newValue1AsNumeric = duplicate.Select(x =>
    {
        if (int.TryParse(Convert.ToString(x[2]), out var value))
            return value;

        return (int?)null;
    }).OfType<int>().Max(); 

    var newValue2 = duplicate.Select(x => x[3]).OfType<int>().Max();

    //enumerate each row of the duplicate
    foreach (var dataRow in duplicate)
        dt.Rows.Remove(dataRow);

    dt.Rows.Add(newId, newText, newValue1, newValue2);
}
DataTable dt=newdatatable();
添加(“Id”,typeof(int));
添加(“文本”,类型(字符串));
添加(“值1”,类型(字符串));
添加(“值2”,类型(int));
添加(1,“测试1”,“584”,12);
添加(2,“测试2”,“32”,123);
添加(3,“测试3”,“425”,54);
添加(4,“测试1”,“4”,755);
添加(5,“测试5”、“854”和879);
添加(6,“Test2”,“1”,null);
添加(7,“测试2”,“999”,3);
var duplicates=dt.Rows.OfType().GroupBy(x=>x[1]),其中(x=>x.Count()>1.ToList();
//获取当前的highestId(第一列),这样当我们删除重复项和新行时,新行将获得下一个可用id
var highestId=dt.Rows.OfType().Max(x=>(int)x[0]);
//列举所有重复项
foreach(var重复中的重复)
{
//获取每列的最大值
var newId=++highestId;
var newText=replicate.Key;
var newValue1=duplicate.Max(x=>x[2]);//这会进行字符串比较,而不是数字比较,这意味着,例如,2大于10
//如果需要数字比较,请使用此选项
var newValue1AsNumeric=重复。选择(x=>
{
if(int.TryParse(Convert.ToString(x[2]),out var值))
返回值;
返回(int?)null;
}).OfType().Max();
var newValue2=duplicate.Select(x=>x[3])of type().Max();
//枚举副本的每一行
foreach(var数据行一式两份)
删除(数据行);
添加(newId、newText、newValue1、newValue2);
}
您可以在此处看到正在运行的代码:

使用DataTable.AsEnumerable()//LINQ 然后使用GroupBy(),//LINQ 过滤记录, 处理它们, 创建新数据表/从同一数据表中删除非必需记录
完成。

我给你的专栏命名是为了让事情变得简单一点:

DataTable dt=newdatatable();
Add(“id”,Type.GetType(“System.Int32”);
Add(“group”,Type.GetType(“System.String”);
Add(“first”,Type.GetType(“System.String”);
Add(“second”,Type.GetType(“System.Int32”);
添加(1,“测试1”,“584”,12);
添加(2,“测试2”,“32”,123);
添加(3,“测试3”,“425”,54);
添加(4,“测试1”,“4”,755);
添加(5,“测试5”、“854”和879);
添加(6,“Test2”,“1”,null);
添加(7,“测试2”,“999”,3);
然后,您可以使用Linq分组并找到最大值(假设这就是您所说的“最佳”的意思):

var group = dt.AsEnumerable().GroupBy(row => row.Field<string>("group")).Select(g => new
{
    group = g.Key,
    first = g.Max(row => int.Parse(row.Field<string>("first"))).ToString(),
    second = g.Max(row => row.Field<int?>("second") ?? 0)
}).ToList();

定义最佳。最大的?谢谢。不幸的是,我应该提到.net的版本。此项目使用的是4.0,是从3.5升级而来的。所以,``var value``不会work@54696d你的问题在哪里?我在.net 4.0中运行这段代码没有问题-正如您在这里看到的,
var value
不是.net Framework功能,而是一种c语言功能,您使用的是哪种c语言版本,为什么坚持使用这个版本?它告诉我“功能‘out variable declaration’在C#4中不可用。请使用7.0或更高版本的语言。好吧,但为什么要坚持使用这种旧版本的语言?
var group = dt.AsEnumerable().GroupBy(row => row.Field<string>("group")).Select(g => new
{
    group = g.Key,
    first = g.Max(row => int.Parse(row.Field<string>("first"))).ToString(),
    second = g.Max(row => row.Field<int?>("second") ?? 0)
}).ToList();
dt.Clear();
var rowCount = 1;
foreach (var x in group)
    dt.Rows.Add(rowCount++, x.group, x.first, x.second);