我有一个有序列表 0,1,2,6,7,10
我想得到数字增加1的集合。 我想要第一个数字和计数或系列。
所以我会得到
start = 0,count = 3
start = 6,count = 2
start = 10,count = 1
我怎样才能在C#中做到这一点?
答案是我认为最好的方式。对我来说,可读性比性能更重要。
答案 0 :(得分:6)
定义一个简单的类来保存结果:
private class Set
{
public int Start = 0;
public int Count = 0;
}
您可以使用以下方法:
private static IEnumerable<Set> GetSets(List<int> src)
{
List<Set> rtn = new List<Set>();
int previous = int.MaxValue;
foreach (int i in src)
{
if (i == previous + 1)
{
rtn[rtn.Count - 1].Count += 1;
}
else
{
rtn.Add(new Set() { Start = i, Count = 1 });
}
previous = i;
}
return rtn;
}
我并不热衷于int.MaxValue
的神奇价值,但它在第一次迭代时节省了额外的逻辑。
正确调用GetSets(new List<int>() { 0, 1, 2, 6, 7, 10 })
会得到您需要的结果。
答案 1 :(得分:2)
试试这个(在LinqPad中作为“C#语句”
var nums = new [] {0, 1, 2, 6, 7, 10};
Debug.Assert(nums.All(i => i >= 0));
Debug.Assert(nums.Zip(nums.Skip(1), (n1, n2) => (n1 < n2)).All(_ => _));
var @group = 0;
nums.Zip(nums.Skip(1).Concat(new [] {nums.Last ()}),
(n1, n2) => Tuple.Create(
n1,
(n2 - n1) == 1 ? @group : @group++))
.GroupBy (t => t.Item2)
.Select (g => new {Group = g.Select(x => x.Item1), Count = g.Count()})
.Dump()
;
答案 2 :(得分:0)
使用扩展方法可能更简洁
public static IEnumerable<IEnumerable<int>> GetConsecutiveCollections(this IEnumerable<int> source)
{
var list = new List<int>();
var start = source.Min() - 1;
foreach (var i in source)
{
if (i == start + 1)
{
list.Add(i);
start = i;
}
else
{
var result = list.ToList();
list.Clear();
list.Add(i);
start = i;
yield return result;
}
}
yield return list;
}
然后以这种方式创建结果:
var result = x.GetConsecutiveCollections()
.Select(c => new { Start = c.Min(), Count = c.Count()});
答案 3 :(得分:0)
产量怎么样?
class GetSetsWithAdjacent
{
public struct CountEm
{
public int start;
public int count;
override public string ToString()
{
return string.Format("start={0}, count={1}", this.start, this.count);
}
}
static public IEnumerable<CountEm> GenCount(int[] inputs)
{
return GenCount(((IEnumerable<int>)inputs).GetEnumerator());
}
static public IEnumerable<CountEm> GenCount(IEnumerator<int> inputs)
{
if (inputs.MoveNext())
{
CountEm result = new CountEm {start = inputs.Current, count = 1 };
while (inputs.MoveNext())
{
if (result.start + result.count == inputs.Current)
{
result.count += 1;
}
else
{
yield return result;
result = new CountEm { start = inputs.Current, count = 1 };
}
}
yield return result;
}
}
}
class StackOverflow
{
private static void Test_GetSetsWithAdjacent()
{
// http://stackoverflow.com/questions/7064157/c-linq-get-sets-with-adjacent
int[] inputs = { 0, 1, 2, 6, 7, 10 };
foreach (GetSetsWithAdjacent.CountEm countIt in GetSetsWithAdjacent.GenCount(inputs))
{
Console.WriteLine(countIt);
}
}
internal static void Test()
{
Test_GetSetsWithAdjacent();
}
}