获取两个数据行中的键值配对差异
本文关键字:键值 数据 两个 获取 | 更新日期: 2023-09-27 18:30:49
好的,所以我需要获取两个数据行的键值配对差异。简而言之,我正在发送一封电子邮件,让用户知道他们已经对他们的个人资料进行了特定的更改。我已经知道行是不同的,因为我正在使用SequenceEqual
来确定这一点。
目前,我已经编写并调试了以下代码:
if (currentRow.ItemArray.SequenceEqual(updatedRow)) { return; }
var updates = currentRow.ItemArray
.Where((o, i) =>
{
if (o == null && updatedRow[i] == null) { return false; }
else if (o == null && updatedRow[i] != null) { return true; }
else if (o.Equals(updatedRow[i])) { return false; }
return true;
})
.Select((o, i) =>
{
return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedRow[i])
};
}).ToList();
但是这段代码有两个问题:
- 对我来说,这似乎非常低效,因为它会遍历
ItemArray
中的每个值,然后在值不同时构建一个键值对。 - 它实际上不起作用,因为发送到
Select
的i
不正确(例如,如果第二列更改,1
,发送到Select
的索引实际上是0
。老实说,这是有道理的,但我不确定如何在这里得到我想要的东西。
约束:我想在这里使用 LINQ。
注意:我只比较两行(即它不会经过行列表)。
对于我在此处尝试执行的操作,适当的 LINQ 语句是什么?
更新:真的感觉我只需要使用:
currentRow.ItemArray.Intersect(updatedRow.ItemArray)
但问题是我不知道那是什么字段,所以我无法构建键值对。换句话说,我只得到差异,但我不知道索引是什么,所以我无法根据这些值获取列名。
老实说,使用for
循环不会丢失太多代码清晰度。
public IEnumerable<AppServices.NotificationData> GetUpdates(DataRow currentRow, DataRow updatedRow)
{
if (currentRow.ItemArray.SequenceEqual(updatedRow)) yield break;
var length = currentRow.ItemArray.Length;
for(var i = 0; i < length; i++)
{
var currentCol = currentRow[i];
var updatedCol = updatedRow[i];
if (currentCol == null && updatedCol == null) continue;
else if (currentCol == null && updatedCol != null) continue;
else if (currentCol.Equals(updatedCol)) continue;
yield return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedCol)
};
}
}
var updates = currentRow.ItemArray
.Select((o, i) => new { Row = o, Index = i })
.Where(r => (r.Row == null && updatedRow[r.Index] != null)
|| (r.Row != null && updatedRow[r.Index] != null
&& !r.Row.Equals(updatedRow[r.Index])))
.Select(r => new
{
Key = updatedRow.Table.Columns[r.Index].ColumnName,
Value = Convert.ToString(updatedRow[r.Index])
}).ToList();
通常,我认为在 LINQ 中使用数组索引值是一种"代码异味",这是一个很好的示例:Where 子句在生成新的值序列时,破坏了 Select 子句正在处理与以前相同的集合的错觉。
现在解决这个问题的一个快速技巧(尽管我认为它还不是正确的解决方案),本质上是交换您的 Where 和 Select 子句:
if (currentRow.ItemArray.SequenceEqual(updatedRow)) { return; }
var updates = currentRow.ItemArray
.Select((o, i) =>
{
if (o == null && updatedRow[i] == null || o.Equals(updatedRow[i])) { return null; }
else return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedRow[i])
};
}).Where(o => o != null).ToList();