gpt4 book ai didi

C# lambda - 两个列表内部列表的差异(除外)

转载 作者:行者123 更新时间:2023-11-30 20:38:42 25 4
gpt4 key购买 nike

我有两个“表”1 ----N“列”的列表。第一个列表包含必须实现的默认模式。第二个列表包含用户定义的模式。我需要将第二个列表与第一个列表进行比较,检索模式不匹配的表,以及缺失/未知列的列表。

考虑以下示例:

public class Table
{
public string Name {get;set;}
public IList<Column> Columns {get;set;}
public Table()
{
Columns = new List<Column>();
}
}
public class Column
{
public string Name {get;set;}
}
//...
var Default1 = new Table() { Name = "Table1" };
Default1.Columns.Add(new Column() { Name = "X1" });
Default1.Columns.Add(new Column() { Name = "X2" });
var Default2 = new Table() { Name = "Table2" };
Default2.Columns.Add(new Column() { Name = "Y1" });
Default2.Columns.Add(new Column() { Name = "Y2" });

var DefaultSchema = new List<Table>() { Default1, Default2 };

var T1 = new Table() { Name = "Table1" };
T1.Columns.Add(new Column() { Name = "X1" });
var T2 = new Table() { Name = "Table2" };
T2.Columns.Add(new Column() { Name = "Y2" });

var MyTables = new List<Table>() { T1, T2};

/*
var DiffTables = DefaultSchema.Join(??).Select(x => x.Columns).Except(?? MyTables.Select(y => y.Columns) ...
*/

预期结果:

var DiffTables =
{
{
Name = "Table1",
Columns =
{
Name = "X2" //Missing from DefaultSchema.Table1
}
},
{
Name = "Table2",
Columns =
{
Name = "Y1" //Missing from DefaultSchema.Table2
}
}
}

有没有办法用 lamdba 表达式或仅通过 master+nested foreach 来做到这一点?

谢谢!

最佳答案

如果只比较两个表,则为:

Default1.Columns
.Select(x => x.Name)
.Except(T1.Columns.Select(x => x.Name));

为了比较两个模式,它将是:

DefaultSchema
.Zip(MyTables, (x, y) => new
{ Name = x.Name,
MissingColumns = x.Columns.Select(x1 => x1.Name)
.Except(y.Columns.Select(y1 => y1.Name)) });

Zip 组合任意两个序列,以便项目 1 与项目 2 匹配,项目 2 与项目 2 匹配,等等(换句话说,就像 zipper 一样)。

Except 从另一个序列中删除一个序列的所有项目。

正如@MetroSmurf 所指出的,我的原始版本有一个错误导致 Except 失败。原因是它根据列是否引用同一对象来比较这些列。我添加了内部 Select 语句以允许通过 Name 来比较列。

另请注意,此答案假设被比较的两个模式具有相同顺序的相同表。


另一种方法(受@MetroSmurf 对IEquatable 的使用的启发)是创建自定义IEqualityComparer,如下所示:

public class ColumnComparer : IEqualityComparer<Column>
{
public bool Equals(Column x, Column y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false;
return x.Name == y.Name;
}

public int GetHashCode(Column column)
{
if (Object.ReferenceEquals(column, null)) return 0;
return column.Name.GetHashCode();
}
}

然后 LINQ 查询简化为:

DefaultSchema.Zip(MyTables, (x, y) => new
{
Name = x.Name,
MissingColumns = x.Columns.Except(y.Columns, new ColumnComparer())
});

同样,两个模式的表相同的假设同样适用。


如果这个假设不适用(即 MyTables 不按顺序或可能缺少表),您可以改用“左外连接”:

var result =
from table in DefaultSchema
join myTable in MyTables on table.Name equals myTable.Name into matchingTables
from matchingTable in matchingTables.DefaultIfEmpty()
select new
{
Name = table.Name,
MissingColumns = matchingTable == null
? null
: table.Columns.Except(matchingTable.Columns, new ColumnComparer())
};

通过此查询,将为 DefaultSchema 中的每个表生成一个结果。如果一个或多个 MyTables 具有相同的名称,则会报告缺少的列。如果 MyTables 中缺少该表,则 MissingColumns 的值为 null。请注意,这不会报告 MyTables 中不存在于 DefaultSchema 中的任何额外表。

关于C# lambda - 两个列表内部列表的差异(除外),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34889101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com