C# 另一个逻辑风暴:我需要快速算法从大列表中获取最后的值<&燃气轮机;根据某种条件
我的数据结构如下:C# 另一个逻辑风暴:我需要快速算法从大列表中获取最后的值<&燃气轮机;根据某种条件,c#,list,data-structures,C#,List,Data Structures,我的数据结构如下: public struct StateItem { public DateTime Moment; public int SomeValue; public int Id { get { return Moment.Hour + Moment.Minute + Moment.Second + SomeValue
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");
}
}
在另一个类中,我不断地将这些项目收集到列表\u项目中,如下所示:
public void Add(StateItem item)
{
if (!_items.Contains(item))
{
_items.Add(item);
}
}
随着时间流项目的不断收集,列表将包含
“2010-11-11 12:33”,1
“2010-11-11 12:33”,2
“2010-11-11 12:33”,1
“2010-11-11 12:33”,第5页
“2010-11-11 12:32”,第5页
“2010-11-11 12:32”,4
所以最后一项是最后一次-这很重要
现在让我们假设列表的末尾是起点,我需要得到N个带M阶跃的力矩帧,e。g、 :
- 1阶跃为0的力矩框架将在“2010-11-11 12:33”时刻返回所有项目
- 具有0阶跃的2力矩框架将在“2010-11-11 12:33”和“2010-11-11 12:32”返回所有项目
- 一个带有一个台阶的力矩框架将在“2010-11-11 12:32”时刻返回所有项目
非常感谢您的任何决定
以下是我自己找到的解决方案:
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;
}
public List GetItems(int-cnt,int-cntfost)
{
var r=新列表();
int i=0;
int-iOffset=0;
int idx=_items.Count-1;
DateTime矩=_items[idx]。矩;
而(i item.SomeValue.CompareTo(logItem.SomeValue));
返回r;
}
我在理解您的问题时遇到了一些困难,但您似乎希望定期从异步填充序列的末尾提取一些项目
如果我是正确的,那么您最好看看,它允许您将事件源视为一个IEnumerable
,并在其上使用Linq。我用这种方法正确理解了您的问题吗?给它你的项目,帧大小和步长值,它会给你一个窗口的结果分组的时刻
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);
}
我看不出你想要什么,但看起来队列或优先队列可能是一个不错的选择?无法启动赏金,因为缺少分数:(如果最后一项是最后一次很重要,那么为什么不呢?我同意Kdansky的观点,你只需要一个队列。或者一个循环缓冲区(有时称为FIFO缓冲区).我不明白这个问题;目前的问题在哪里?很难解读\u dates
的意图(例如)…是的,你是对的,但关键是机制本身-快速而简单:)@skaeff:机制呢?Rx有什么不快速、不简单的地方?请你把你的要求说清楚一点好吗?是的,这是正确的,但正如我所理解的,你的代码扫描所有的列表并对其进行分组,然后排序,然后过滤。如果是这样的话,这在性能上是不好的,因为列表已经足够大了。我需要检查一下列表的尾部
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;
}
}
}