LINQ、SelectMany 具有多种可能的结果

发布于 2024-11-06 08:34:03 字数 1564 浏览 0 评论 0原文

我遇到的情况是,我有必须合并的对象列表。列表中的每个对象都有一个属性,用于解释在合并中应如何处理它。所以假设如下..

enum Cascade {
  Full,
  Unique,
  Right,
  Left
}

class Note {
  int Id { get; set; }
  Cascade Cascade { get; set; }
  // lots of other data.
}

var list1 = new List<Note>{
 new Note {
   Id = 1,
   Cascade.Full,
   // data
 },
 new Note {
   Id = 2,
   Cascade.Right,
   // data
 }
};
var list2 = new List<Note>{
  new Note {
   Id = 1,
   Cascade.Left,
   // data
  }
};
var list3 = new List<Note>{
  new Note {
    Id = 1,
    Cascade.Unique,
    // data similar to list1.Note[0]
  }
}

那么,我将有一个方法...

Composite(this IList<IList<Note>> notes){
  return new List<Note> {
      notes.SelectMany(g => g).Where(g => g.Cascade == Cascade.All).ToList()
      // Here is the problem... 
      .SelectMany(g => g).Where(g => g.Cascade == Cascade.Right)
      .Select( // I want to do a _LastOrDefault_ )
      // continuing for the other cascades. 
  }
}

这就是我迷路的地方。我需要执行多个 SelectMany 语句,但我不知道该怎么做。但这是预期的行为

Cascade.Full

无论如何,Note 都将出现在最终集合中。

Cascade.Unique

Note 将出现在最终集合中一次,忽略任何重复项。

Cascade.Left

Note 将位于最终集合中,第一个 实例将取代后续实例。 (因此,注释 1、2、3 是相同的。注释 1 被推送)

Cascade.Right

Note 将位于最终集合中,Last< /strong> 实例取代重复项。 (所以注释 1、2、3 是相同的。注释 3 被推入低谷)

I have a situation where I have lists of objects that have to be merged. Each object in the list will have a property that explains how it should be treated in the merger. So assume the following..

enum Cascade {
  Full,
  Unique,
  Right,
  Left
}

class Note {
  int Id { get; set; }
  Cascade Cascade { get; set; }
  // lots of other data.
}

var list1 = new List<Note>{
 new Note {
   Id = 1,
   Cascade.Full,
   // data
 },
 new Note {
   Id = 2,
   Cascade.Right,
   // data
 }
};
var list2 = new List<Note>{
  new Note {
   Id = 1,
   Cascade.Left,
   // data
  }
};
var list3 = new List<Note>{
  new Note {
    Id = 1,
    Cascade.Unique,
    // data similar to list1.Note[0]
  }
}

So then, I'll have a method ...

Composite(this IList<IList<Note>> notes){
  return new List<Note> {
      notes.SelectMany(g => g).Where(g => g.Cascade == Cascade.All).ToList()
      // Here is the problem... 
      .SelectMany(g => g).Where(g => g.Cascade == Cascade.Right)
      .Select( // I want to do a _LastOrDefault_ )
      // continuing for the other cascades. 
  }
}

This is where I get lost. I need to do multiple SelectMany statements, but I don't know how to. But this is the expected behavior.

Cascade.Full

The Note will be in the final collection no matter what.

Cascade.Unique

The Note will be in the final collection one time, ignoring any duplicates.

Cascade.Left

The Note will be in the final collection, First instances superseding subsequent instances. (So then, Notes 1, 2, 3 are identical. Note 1 gets pushed through)

Cascade.Right

The Note will be in the final collection, Last instance superseding duplicates. (So Notes 1, 2, 3 are identical. Note 3 gets pushed trough)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

给妤﹃绝世温柔 2024-11-13 08:34:03

我认为你应该把问题分解成更小的部分。例如,您可以在单独的扩展方法中实现单个列表的级联规则。这是我未经测试的看法:

public static IEnumerable<Note> ApplyCascades(this IEnumerable<Note> notes)
    {
        var uniques = new HashSet<Note>();
        Note rightToYield = null;
        foreach (var n in notes)
        {
            bool leftYielded = false;

            if (n.Cascade == Cascade.All) yield return n;
            if (n.Cascade == Cascade.Left && !leftYielded)
            {
                yield return n;
                leftYielded = true;
            }
            if (n.Cascade == Cascade.Right)
            {
                rightToYield = n;
            }
            if (n.Cascade == Cascade.Unique && !uniques.Contains(n))
            {
                yield return n;
                uniques.Add(n);
            } 
        }

        if (rightToYield != null) yield return rightToYield;
    } 
}

此方法将允许实现原始扩展方法,如下所示:

    List<Note> Composite(IList<IList<Note>> notes)
    {
        var result = from list in notes
                     from note in list.ApplyCascades()
                     select note;
        return result.ToList();

    }

I think you should decompose the problem in smaller parts. For example, you can implement the cascade rules for an individual list in a seperate extension method. Here's my untested take at it:

public static IEnumerable<Note> ApplyCascades(this IEnumerable<Note> notes)
    {
        var uniques = new HashSet<Note>();
        Note rightToYield = null;
        foreach (var n in notes)
        {
            bool leftYielded = false;

            if (n.Cascade == Cascade.All) yield return n;
            if (n.Cascade == Cascade.Left && !leftYielded)
            {
                yield return n;
                leftYielded = true;
            }
            if (n.Cascade == Cascade.Right)
            {
                rightToYield = n;
            }
            if (n.Cascade == Cascade.Unique && !uniques.Contains(n))
            {
                yield return n;
                uniques.Add(n);
            } 
        }

        if (rightToYield != null) yield return rightToYield;
    } 
}

This method would allow to implement the original extension method something like this:

    List<Note> Composite(IList<IList<Note>> notes)
    {
        var result = from list in notes
                     from note in list.ApplyCascades()
                     select note;
        return result.ToList();

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文