在集合中查找具有相同值的块并操纵周围值

时间:2014-03-20 11:30:47

标签: c# linq collections

我真的不知道如何总结标题中的问题,对不起。 :)

假设我有一个包含数千个对象的集合(即ObservableCollection)。这些对象由升序时间戳和FALSE布尔值(非常简化)组成。

像这样:

[0] 0.01, FALSE
[1] 0.02, FALSE
[2] 0.03, FALSE
[3] 0.04, FALSE
...

现在,让我们假设在这个集合中,有些块的标志设置为TRUE

像这样:

[2345] 23.46, FALSE
[2346] 23.47, FALSE
[2347] 23.48, FALSE
[2348] 23.49, TRUE
[2349] 23.50, TRUE
[2350] 23.51, TRUE
[2351] 23.52, TRUE
[2352] 23.53, TRUE
[2353] 23.54, FALSE
[2354] 23.55, FALSE
...

我需要找到块并在块之前和之后的1.5秒内将所有标志设置为TRUE。 如何在保持合理性能的同时实现这一目标?

2 个答案:

答案 0 :(得分:2)

马蒂亚斯G解决方案是正确的,虽然很慢 - 似乎有n平方的复杂性。

首先扫描输入values以通过IsActive过滤它们,检索时间戳并放入新列表 - 至少是O(n)。然后它扫描构造的列表,在最坏的情况下可能是整个输入 - O(n),并且对于检索到的每个时间戳,它扫描输入values以修改它们的适当值 - O(n ^ 2)。 然后它构建额外的列表只是为了扫描一次并销毁。

我建议一个类似于mergesort的解决方案。首先扫描输入值,并为每个活动项目将适当的时间间隔推入队列。您可以延迟推送以查看下一个间隔是否与当前间隔重叠 - 然后延长间隔而不是推动。输入列表完成后,最后按下最后一个延迟间隔。这样,您的队列将包含您想要修改的(几乎)最少数量的时间间隔。

然后再次扫描values数据并将时间戳与队列中的第一个间隔进行比较。如果项目的时间戳落入当前间隔,请将项目标记为“活动”。如果它超过了间隔,则从队列中删除间隔并将时间戳与下一个时间戳进行比较 - 依此类推,直到该项位于间隔中或之前。您的输入数据按时间顺序排列,因此间隔也将按相同的顺序排列。这允许通过两个列表在单个并行传递中完成任务。

答案 1 :(得分:1)

假设您有这样的数据结构:

修改:将TimeStamp更改为double

public class Value
{
    public double TimeStamp { get; set; }

    public bool IsActive { get; set; }
}

此对象的列表名为values。然后,您可以搜索活动数据集,并为每个数据集将它们周围的值标记为活动数据:

double range = 1.5;
var activeTimeStamps = values.Where(value => value.IsActive)
                             .Select(value => value.TimeStamp)
                             .ToList();
foreach (var timeStamp in activeTimeStamps)
{
    var valuesToMakeActive =
        values.Where
            (
                value =>
                    value.TimeStamp >= timeStamp - range &&
                    value.TimeStamp <= timeStamp + range
            );
    foreach (var value in valuesToMakeActive)
    {
        value.IsActive = true;
    }
}

无论如何,我想会有一个性能更好的解决方案..