LINQ - 合并保留顺序的列表元素(功能思维)
本文关键字:功能 列表元素 合并 保留 顺序 LINQ | 更新日期: 2023-09-27 18:31:47
我有一个sql语句列表,作为
List<IStatement>
- 从表 A 更新集合 a.col1=1
- 从表 A 更新集合 a.col2=2
- 从表 A 更新集合 a.col3=3
- 从表A 中选择 a.Col1,a.Col2,a.Col3
- 更新 b 从表 B b 设置 b.col1=1
- 更新 b 从表 B b 设置 b.col2=2
- 从表B b 中选择 b.Col1,b.Col2
突出类包括:
- 选择声明 : IStatement
- 更新声明 : 目录
更新声明有一个
- 返回 From 子句的 GetFrom 方法
- 返回 IEnumerable 的 GetSets 方法
- AddSet 方法,该方法将新的 Set 表达式添加到现有 Set
我有一个 IsEqualTo 扩展方法来比较 From 子句
我正在尝试使用 Linq 聚合运算符将更新语句合并为单个更新语句,同时保留顺序,以便最终列表为 .
- 从表 A 更新集合 a.col1=1,a.col2=2,a.col3=3
- 从表A 中选择 a.Col1,a.Col2,a.Col3
- 更新 b 从表 B 设置 b.col1=1,b.col2=2
- 从表B b 中选择 b.Col1,b.Col2
我正在考虑使用聚合来尝试这样做 - 到目前为止,我的代码是
Dim mergeUpdates = Function(statements As IList(Of IStatement), statement As IStatement)
If statements.Count = 0 Then Return statements.AddItem(statement)
If Not TypeOf statement Is UpdateStatement Then Return statements.AddItem(statement)
Dim u = DirectCast(statement, UpdateStatement)
Dim t = (From st In statements
Where TypeOf st Is UpdateStatement
Let uSt = DirectCast(st, UpdateStatement)
Where uSt.GetFrom.IsEqualTo(u.From)
Select uSt).First.AddSet(u.Set)
Return statements.AddItem(t)
End Function
Return statements.Aggregate(New List(Of IStatement), Function(ss, s) mergeUpdates(ss, s)))
但现在我不确定 Linq 聚合是否是正确的方法。(我知道以上是不完整的)
我将不胜感激任何指向正确 (FP) 执行此操作方式的指针。
首先,您需要将相关的更新语句组合在一起:
var groupedStatements = statements
.GroupBy(s=>new {IsUpdate= (s is UpdateStatement), From=s.GetFrom()});
GroupBy 将对相关的更新语句进行分组,即使它们在您的列表中不是连续的。如果您只想对连续语句进行分组,则需要像这样或这样一种替代 GroupBy 的方法。
这假设所有 IStatements 都有一个 GetFrom(),如果没有,您将需要使用 ?
运算符进行一些技巧。此外,它还要求 From
类实现 IEquatable,以允许 GroupBy 运算符检查相同的 from 子句。如果没有,则需要将 from 子句转换为字符串或其他内容,以允许比较。
然后,合并每个更新组的元素,并保持其他组不变
var combinedStatements = groupedStatements
.SelectMany(group=>group.Key.IsUpdate
? Enumerable.Repeat<IStatement>(new UpdateStatement (group.Key.From, group.Select(s=>s.GetSets())),1)
: group.Select(s=>s);
在这里,您需要一种方法来创建新的 UpdateStatement,例如采用 from 子句和 IEnumerable of Set 子句的构造函数。SelectMany 将生成的语句列表折叠为单个语句列表。请注意,Enumerable.Repeat(s,1) 用于仅包含一个元素创建新的 IEnumerable。