我的数据结构如下:
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中,如下所示:
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个矩帧,例如:
任何决定都是非常感谢的!
下面是我自己找到的解决办法:
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;
}发布于 2010-11-11 11:08:52
我在理解您的问题时遇到了一些困难,但似乎您希望定期从异步填充序列的末尾提取一些项。
如果我是正确的,那么您最好查看一下Rx框架,它允许您将事件源视为IEnumerable并在其上使用Linq。
发布于 2010-11-11 11:39:42
用这种方法我明白你的问题了吗?给它你的项目,框架大小和stepOff值,它将给你一个窗口的结果按时间分组。
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);
}如果这给出了正确的输出,您可以使用它作为改进性能的基础,可能是通过使用预先预置输入数据的要求来替换GroupBy和OrderByDescending。不过,Skip和Take都很棒。
更新
奇怪的是,午饭时我一直在想这件事。这里有一个基于yield操作符的替代解决方案,它提供输入列表按Moment排序。
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;
}
}
}https://stackoverflow.com/questions/4153590
复制相似问题