Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 执行;除「;使用特定列_C#_Linq_Datatable_Except - Fatal编程技术网

C# 执行;除「;使用特定列

C# 执行;除「;使用特定列,c#,linq,datatable,except,C#,Linq,Datatable,Except,考虑具有相同架构的两个表: var yesterday = new DataTable(); yesterday.Columns.Add("id", typeof(int)); yesterday.Columns.Add("part_number", typeof(string)); yesterday.Columns.Add("description", typeof(string)); yesterday.Columns.Add("comment", typeof(string)); yes

考虑具有相同架构的两个表:

var yesterday = new DataTable();
yesterday.Columns.Add("id", typeof(int));
yesterday.Columns.Add("part_number", typeof(string));
yesterday.Columns.Add("description", typeof(string));
yesterday.Columns.Add("comment", typeof(string));
yesterday.Columns.Add("information", typeof(string));
yesterday.Columns.Add("data", typeof(string));
var today = yesterday.Clone();
添加一些数据:

//yesterday data has 3 rows
yesterday.Rows.Add(1, "IVD_002", "IVD_002_RED", "Some comment", "Some information","Some data");
yesterday.Rows.Add(2, "IVD_003", "IVD_003_RED", "Some comment", "Some information", "Some data");
yesterday.Rows.Add(3, "IVD_004", "IVD_004_RED", "Some comment", "Some information", "Some data");

//today's data has the same 3 rows
today.Rows.Add(1, "IVD_002", "IVD_002_RED", "Some comment", "Some information", "Some data");
today.Rows.Add(2, "IVD_003", "IVD_003_RED", "Some comment", "Some information", "Some data");
today.Rows.Add(3, "IVD_004", "IVD_004_RED", "Some comment", "Some information", "Some data");
让我们添加更多数据:

//The New Row:
//In the output table I expect to see only the following row. The "id" column is 5 whereas in previous records there is no row with id = 5, part_number = IVD_002, description = IVD_002_RED
today.Rows.Add(5, "IVD_002", "IVD_002_RED", "Some comment", "Some information", "Some data");

//Another New Row:
//I dont expect to see this row in the result table because we are doing except only on "id","part_number","description" columns
today.Rows.Add(1, "IVD_002", "IVD_002_RED", "ROSES ARE RED", "PEANUTS", "=)");
我的目标是从“今天”表中获取行,除了“昨天”表中的行,但只比较“id”、“part_number”、“description”列


非常感谢纯LINQ解决方案,不带循环。

我想我得到了。还有更好的办法吗

var result = today.AsEnumerable()
    .Where(r =>
        today.AsEnumerable()
            .Select(r =>
                new { id = r["id"].ToString(), part_number = r["part_number"].ToString(), description = r["description"].ToString() })
            .Except(yesterday.AsEnumerable()
                .Select(r =>
                    new { id = r["id"].ToString(), part_number = r["part_number"].ToString(), description = r["description"].ToString() }))
            .Contains(new { id = r["id"].ToString(), part_number = r["part_number"].ToString(), description = r["description"].ToString() }))
    .CopyToDataTable();

我建议使用
!任何
。我更愿意将
昨天
数据表
转换为
哈希集
,这样您就不会一直线性扫描
昨天
以查找匹配项,但我不确定UiPath有什么限制

var result = today.AsEnumerable().Where(t => !yesterday.AsEnumerable().Any(y => (y["id"].Equals(t["id"]) &&
                                                                                 y["part_number"].Equals(t["part_number"]) &&
                                                                                 y["description"].Equals(t["description"]))))
                                 .CopyToDataTable();
如果可以使用
哈希集
,则可以执行以下操作:

var yesterdayHash = yesterday.AsEnumerable().Select(y => new { id = (int)y["id"], partnum = y["part_number"].ToString(), desc = y["description"].ToString() }).ToHashSet();
var result2 = today.AsEnumerable().Where(t => !yesterdayHash.Contains(new { id = (int)t["id"], partnum = t["part_number"].ToString(), desc = t["description"].ToString() })).CopyToDataTable();
使用用于创建返回匿名类型的
Func
委托的静态类强制转换帮助器,可以创建lambda变量来保存公共键表达式:

public static class To {
    public static Func<TResult> Func<TResult>(Func<TResult> func) => func;
    public static Func<T, TResult> Func<T, TResult>(Func<T, TResult> func) => func;
}

var selectorFn = To.Func((DataRow r) => new { id = r.Field<int>("id"), partnum = r.Field<string>("part_number"), desc = r.Field<string>("description") });
var yesterdayHash2 = yesterday.AsEnumerable().Select(selectorFn).ToHashSet();
var result3 = today.AsEnumerable().Where(t => !yesterdayHash2.Contains(selectorFn(t))).CopyToDataTable();
public静态类到{
公共静态Func Func(Func Func)=>Func;
公共静态Func Func(Func Func)=>Func;
}
var selectorFn=To.Func((数据行r)=>new{id=r.Field(“id”)、partnum=r.Field(“零件号”)、desc=r.Field(“说明”)});
var yesterdayHash2=beday.AsEnumerable().Select(selectorFn.ToHashSet();
var result3=today.AsEnumerable().Where(t=>!yesterdayHash2.Contains(selectorFn(t)).CopyToDataTable();

注意:我更喜欢在
DataRow
上使用
字段
扩展方法来获取强类型的
DataTable
列值。

您需要类似的内容此解决方案旨在用于UiPath,因此我对代码的处理能力相当有限。LINQ查询应该是最佳的。@SalahAkbari这是一个数据表,而不是自定义对象的列表。@juharr我相信这仍然是可能的,因为
DataTable
仍然是一个对象。有没有办法将“新”结构分配给变量?列数组还是smth?因此,我不会重复输入相同的3次如果您可以创建一个lambda变量,您可以执行
var selectorFn=(DataTable r)=>new{id=r[“id”].ToString(),part_number=r[“part_number”].ToString(),description=r[“description”].ToString()
然后使用它
today.AsEnumerable().Where(r=>today.AsEnumerable().Select(selectorFn).除了(Dayed.AsEnumerable().Select(selectorFn)).Contains(selectorFn(r)).CopyToDataTable()
。您需要一个静态强制转换帮助程序才能工作。请参阅我的答案更新。现在这是一个真正的法师。非常感谢!对于UiPath中的HashSet,不幸的是它不能很好地处理匿名类型,所以我必须坚持使用选项#1