首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何选择集合中多个子类别的最后两个实例?

如何选择集合中多个子类别的最后两个实例?
EN

Stack Overflow用户
提问于 2015-11-18 10:14:53
回答 3查看 64关注 0票数 0

Stackoverflow

使用C# LINQ,如何选择集合中多个子类别的最后两个实例?

在下面的代码中,phaseRepository是一个阶段列表。

每个阶段都有一些属性,包括方向和动量(其中Momentum.Undefined应该被认为与Momentum.Time相同)。您将如何为四个子类别选择最后两个阶段实例:

  • Direction.Up & Momentum.Price
  • Direction.Up & Momentum.Time (平等对待.Time和.Undefined )
  • Direction.Down & Momentum.Price
  • Direction.Down & Momentum.Time (平等对待.Time和.Undefined )

答案类似于(不需要PhaseNumber命令):

为了提供帮助,下面的代码是一个LINQPad C#程序,它编译但缺少正确的答案:

代码语言:javascript
复制
void Main()
{
    var phaseRepository = new PhaseRepository();
    phaseRepository.Collection = GetCollection();

    // answer in its current state is incorrect...
    var answer = phaseRepository.Collection.Select(p => p);

    answer.Dump();  
}

private List<Phase> GetCollection() 
{
    return new List<Phase>
    {
        new Phase ()
        {
            PhaseNumber = 1,
            Direction = Dir.Up,
            Momentum = Mom.Price,
        },
        new Phase ()
        {
            PhaseNumber = 2,
            Direction = Dir.Down,
            Momentum = Mom.Time,
        },
        new Phase ()
        {
            PhaseNumber = 3,
            Direction = Dir.Up,
            Momentum = Mom.Price,
        },
        new Phase ()
        {
            PhaseNumber = 4,
            Direction = Dir.Down,
            Momentum = Mom.Time,
        },
        new Phase ()
        {
            PhaseNumber = 5,
            Direction = Dir.Up,
            Momentum = Mom.Time,
        },
        new Phase ()
        {
            PhaseNumber = 6,
            Direction = Dir.Down,
            Momentum = Mom.Undefined,
        },
        new Phase ()
        {
            PhaseNumber = 7,
            Direction = Dir.Up,
            Momentum = Mom.Price,
        },
        new Phase ()
        {
            PhaseNumber = 8,
            Direction = Dir.Down,
            Momentum = Mom.Price,
        },
        new Phase ()
        {
            PhaseNumber = 9,
            Direction = Dir.Up,
            Momentum = Mom.Price,
        },
        new Phase ()
        {
            PhaseNumber = 10,
            Direction = Dir.Down,
            Momentum = Mom.Time,
        },
        new Phase ()
        {
            PhaseNumber = 11,
            Direction = Dir.Up,
            Momentum = Mom.Time,
        },
        new Phase ()
        {
            PhaseNumber = 12,
            Direction = Dir.Down,
            Momentum = Mom.Undefined,
        }
    };
}

public class PhaseRepository
{
    public List<Phase> Collection = new List<Phase>();
}   

public class Phase
{
    public int PhaseNumber { get; set; }
    public Dir Direction { get; set; }
    public Mom Momentum { get; set; }
}

public enum Dir
{
    Up,
    Down,
    Undefined
}

public enum Mom
{
    Price,
    Time,
    Undefined
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-11-18 10:36:32

GroupBySelectMany结合起来很容易做到:

代码语言:javascript
复制
var answer = phaseRepository.Collection
    .OrderBy(p => p.PhaseNumber); // prepare to enforce "last two" requirement
    .GroupBy(p =>
         new { 
            p.Direction, 
            Momentum = p.Momentum == Mom.Undefined ? Mom.Time : p.Momentum
         })
    .SelectMany(g => g.Skip(g.Count() - 2)) // skip all but 2 from each group
    .OrderBy(p => p.PhaseNumber); // optional, to make verification easier

这里最重要的一点是,GroupBy有保证,可以在每个组中保留源序列中元素的相对顺序:

IGrouping对象是根据源元素的顺序生成的,这些元素产生每个IGrouping的第一个键。分组中的元素是按照生成它们的元素出现在源中的顺序产生的。

因此,初始的逐阶段排序最初就足以满足“每个组中的最后两个”的要求。

票数 1
EN

Stack Overflow用户

发布于 2015-11-18 10:24:06

对于Direction.Up & Momentum.Price:

代码语言:javascript
复制
phaseRepository.Where(phase =>
{
    phase.Direction == Direction.Up &&
    phase.Momentum == Momentum.Price
}).Reverse().Take(2);

您可以将此应用于所有其他需求。如果您希望未定义的时间与时间相同,只需检查phase.Momentum == Momentum.Time || phase.Momentum == Momentum.Undefined

如果您想要最后一个2 PhaseNumbers,那么在这个数字上使用OrderByDescending(x => x.PhaseNumber),然后从它中使用.Take(2)

如果Where()返回的元素少于2个,则Take(2)仍将返回一个空列表(如果Where()返回1项,则返回1个元素)。

票数 0
EN

Stack Overflow用户

发布于 2015-11-18 10:26:51

像这样的东西应该能起作用

代码语言:javascript
复制
phaseRepository.Collection
    .GroupBy(x => Tuple.Create(x.Direction, x.Momentum))
    .Where(x => x.Key == //filter on your desired sub catagories
    .Select(x => x.OrderBy(y=>y.PhaseNumber).Take(2).ToList()) //get just the last 2 items
    .SelectMany(x => x)
    .OrderBy(y=>PhaseNumber) //return in complete order
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33777260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档