如何将序列元素分组超过阈值?

时间:2013-05-27 13:14:41

标签: c# .net algorithm linq grouping

我正在寻找一种用于对序列中的元素进行分组的算法 例如:
我有以下列表:

1 2 3 4 5 11 11 12 13 3 5 6 11 22 12 24 5 6 22 33

我想查找超过3项且值大于10的所有序列。

所以我会得到:

11 11 12 13

11 22 12 24

我可以使用Linq查询吗?最好的方法是什么?

4 个答案:

答案 0 :(得分:4)

这是我的LinqPad版本。不确定你是否想要这个: - )

void Main() {
    var data = new int[] { 1, 2, 3, 4, 5, 11, 11, 12, 13, 3, 5, 6, 11, 22, 12, 24, 5, 6, 22, 33 };
    var t = 10;  // threshold
    var m = 3;   // max-in-group
    var result = Enumerable.Range(0, data.Length)
        .Select(x => new { 
            // the sequence
            d = data.Skip(x).TakeWhile(y => y > t).ToList(),
            // an indicator is the previous was empty
            // we need this to remove unwanted sequences
            p = x > 0 ? !data.Skip(x - 1).TakeWhile(y => y > t).Any() : true 
        })
        .Where(x => x.p && x.d.Count() > m)
        .Select(x => x.d);
    // LinqPad method to show the value of variable result.
    result.Dump();
}

答案 1 :(得分:2)

LINQ不是您最好的选择,因为您需要有关前后项目的信息才能获得结果。一个简单的循环将是实现它的最简单方法:

var result = new List<List<int>>();

var sequence = new List<int>();
foreach(var item in original)
{
    if(item <= 10)
    {
        if(sequence.Count > 3)
            result.Add(sequence);
        sequence = new List<int>();
    }
    else
        sequence.Add(item);
}

if(sequence.Count > 3)
    result.Add(sequence);

答案 2 :(得分:2)

这不是最漂亮的代码,但它有效。

它也只在输入数组上重复一次

编辑:在代码中做了一些小改动:

  1. 添加itemInSequence,现在可以更改序列大小
  2. 在循环后删除if检查 - 不需要它

        var result = new List<List<int>>();
        int itemInSequence = 4;
    
        List<int> sequence = new List<int>();
        foreach (var item in arrInt)
        {
            if (item < 10)
            {
                sequence.Clear();
                continue;
            }
    
            sequence.Add(item);
            if (sequence.Count == itemInSequence)
            {
                result.Add(sequence.ToList());
                sequence = sequence.GetRange(1, itemInSequence - 1);
            }
        }
    

答案 3 :(得分:1)

使用LINQ似乎在这里被迫。这是使用foreach的解决方案。它只访问每个元素一次。

var list = new[] { 1, 2, 3, 4, 5, 11, 11, 12, 13, 3, 5, 6, 11, 22, 12, 24, 5, 6, 22, 33 };

var cur = new List<int>();
var result = new List<List<int>>();
foreach (var ele in list)
{
    if (ele > 10)
        cur.Add(ele); // Add to current sequence
    else
    {
        if (cur.Count > 3)
            result.Add(cur); // Current sequence is valid
        cur = new List<int>(); // Start new sequence
    }
}
if (cur.Count > 3)
    result.Add(cur); // Final sequence is valid