我正在寻找一种用于对序列中的元素进行分组的算法。
示例:
我有以下列表:
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 查询吗?最好的方法是什么?
这是我的 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();
}
这不是最漂亮的代码,但它可以工作。
它也只遍历输入数组一次
编辑:对代码做了一些小的改动:
itemInSequence
所以现在可以更改序列大小删除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);
}
}
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);
在这里使用 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