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) 执行此操作方式的指针。

LINQ - 合并保留顺序的列表元素(功能思维)

首先,您需要将相关的更新语句组合在一起:

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。