首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >另一个逻辑脑风暴:我需要快速算法,根据某些条件从大型List<>中获取最后值。

另一个逻辑脑风暴:我需要快速算法,根据某些条件从大型List<>中获取最后值。
EN

Stack Overflow用户
提问于 2010-11-11 10:47:16
回答 2查看 118关注 0票数 0

我的数据结构如下:

代码语言:javascript
复制
public struct StateItem
{
    public DateTime Moment;
    public int SomeValue;

    public int Id
    {
        get
        {
            return Moment.Hour
            + Moment.Minute
            + Moment.Second
            + SomeValue
            ;
        }
    }

    public override bool Equals(object obj)
    {
        return Id.Equals(((StateItem)obj).Id);
    }

    public override int GetHashCode()
    {
        return Id;
    }

    public override string ToString()
    {
        return Moment.ToString("HH:mm:ss");
    }

}

在另一个类中,我连续地将这些项目收集到列表<StateItem> _items中,如下所示:

代码语言:javascript
复制
    public void Add(StateItem item)
    {
            if (!_items.Contains(item))
            {
                _items.Add(item);
            }
    }

随着时间流动,项目被连续收集,所以列表中应该包含

“2010-11- 12:33",1

“2010-11- 12:33",2

“2010-11- 12:33",1

“2010-11- 12:33",5

“2010-11- 12:32",5

“2010-11- 12:32",4

所以最后一个项目是最后一次-这很重要!

现在,假设列表的结尾是起点,我需要得到M stepOff的N个矩帧,例如:

  • 1具有0 stepOff的矩帧将在"2010-11-11 12:33“时刻返回所有项目。
  • 2具有0 stepOff的矩帧将在"2010-11-11 12:33“和"2010-11-11 12:32”返回所有项目。
  • 一个带有1 stepOff的矩框将在"2010-11-11 12:32“时刻返回所有项目。

任何决定都是非常感谢的!

下面是我自己找到的解决办法:

代码语言:javascript
复制
 public List<StateItem> GetItems(int cnt, int cntOffset)
    {
            var r = new List<StateItem>();

            int i = 0;
            int iOffset = 0;

            int idx = _items.Count - 1;
            DateTime moment = _items[idx].Moment;

            while (i <= cnt)
            {
                if (iOffset != cntOffset)
                {
                    if (!_items[idx].Moment.Equals(moment))
                    {
                        iOffset++;
                        moment = _items[idx].Moment;
                        continue;
                    }
                    moment = _items[idx].Moment;
                    idx--;
                    continue;
                }

                if (_items[idx].Moment.Equals(moment))
                {
                    r.Add(_items[idx]);
                }
                else
                {
                    i++;
                    moment = _items[idx].Moment;
                    continue;
                }

                moment = _items[idx].Moment;
                idx--;

            }
            r.Sort((item, logItem) => item.SomeValue.CompareTo(logItem.SomeValue));

            return r;

    }
EN

回答 2

Stack Overflow用户

发布于 2010-11-11 11:08:52

我在理解您的问题时遇到了一些困难,但似乎您希望定期从异步填充序列的末尾提取一些项。

如果我是正确的,那么您最好查看一下Rx框架,它允许您将事件源视为IEnumerable并在其上使用Linq。

票数 0
EN

Stack Overflow用户

发布于 2010-11-11 11:39:42

用这种方法我明白你的问题了吗?给它你的项目,框架大小和stepOff值,它将给你一个窗口的结果按时间分组。

代码语言:javascript
复制
static IEnumerable<IGrouping<DateTime, StateItem>> Foo(IEnumerable<StateItem> items, int frameSize, int stepOff)
{
    return items.GroupBy(i => i.Moment).OrderByDescending(i => i.Key).Skip(stepOff).Take(frameSize);
}

如果这给出了正确的输出,您可以使用它作为改进性能的基础,可能是通过使用预先预置输入数据的要求来替换GroupByOrderByDescending。不过,SkipTake都很棒。

更新

奇怪的是,午饭时我一直在想这件事。这里有一个基于yield操作符的替代解决方案,它提供输入列表按Moment排序。

代码语言:javascript
复制
static IEnumerable<StateItem> BetterFoo(IEnumerable<StateItem> items, int frameSize, int stepOff)
{
    // Handle empty sequence
    if (!items.Any())
        yield break;

    DateTime currentMoment = items.First().Moment;

    foreach (StateItem item in items)
    {
        // stepOff is how many moments to skip
        if (stepOff == 0)
        {               
            // Return the specified number of distinct moments
            if (currentMoment != item.Moment)
            {
                frameSize--;
                currentMoment = item.Moment;
            }

            if (frameSize == 0)
                // Break when we've returned the specified number of frames
                break;
            else
                // Yield the current item
                yield return item;
        }
        else
        {
            // Skip the specified number of distinct moments
            if (currentMoment != item.Moment)
            {
                stepOff--;
                currentMoment = item.Moment;
            }

            if (stepOff == 0)
                yield return item;
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4153590

复制
相关文章

相似问题

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