2017-10-05 180 views
-2

有没有简单的(linq?)方法将int数组拆分为基于不间断数字序列的新数组?例如,给定这样的伪代码:按序列中的值拆分数组

[Fact] 
public void ArraySpike() 
{ 
    var source = new[] {1, 2, 3, 7, 8, 9, 12, 13, 24}; 

    var results = SplitArray(source); 

    Assert.True(results[0] == new[] {1, 2, 3}); 
    Assert.True(results[1] == new[] {7, 8, 9}); 
    Assert.True(results[2] == new[] {12, 13}); 
    Assert.True(results[3] == new[] {24}); 
} 

public int[][] SplitArray(int[] source) 
{ 
    return source.??? 
} 
+0

什么构成组?每5位数字? (1-5,6-10,11-15等)? – Igor

+0

@igor否,连续数字,所以group1 = 1,2,3 group2 = 7,8,9 group3 = 12,13 group4 = 24 – mxmissile

+1

啊,那只是一个巧合而已。 – Igor

回答

1

这可以通过扩展LINQ工作Aggregate。我的播种不是很优雅但是很容易改变。 results变量将包含数组的数组,并且它们实际上是List<T>类型的数据,因为它们可以轻松地在数组[]始终为固定大小的函数中生长。

这还假定源已经下令,独特的,如果情况并非如此添加.OrderBy(x => x).Distinct()

var source = new[] { 1, 2, 3, 7, 8, 9, 12, 13, 24 }; 
var results = new List<List<int>>{new List<int>()}; 

var temp = source.Aggregate(results[0], (b, c) => 
{ 
    if (b.Count > 0 && b.Last() != c - 1) 
    { 
     b = new List<int>(); 
     results.Add(b); 
    } 
    b.Add(c); 
    return b; 
}); 
1

我从我的个人收藏挖出了这个扩展方法:

public static IEnumerable<IEnumerable<T>> GroupConnected<T>(this IEnumerable<T> list, Func<T,T,bool> connectionCondition) 
{ 
    if (list == null) 
    { 
     yield break; 
    } 
    using (var enumerator = list.GetEnumerator()) 
    { 
     T prev = default(T); 
     var temp = new List<T>(); 
     while (enumerator.MoveNext()) 
     { 
      T curr = enumerator.Current; 
      { 
       if(!prev.Equals(default(T)) && !connectionCondition(prev, curr)) 
       { 
        yield return temp; 
        temp = new List<T>(); 
       } 
       temp.Add(curr); 
      } 
      prev = curr; 
     } 
     yield return temp; 
    } 
} 

它解决了在更一般意义上的问题:在元素的子序列分割序列以某种方式“连接”。它遍历序列并收集临时列表中的每个元素,直到下一个项目不“连接”。然后它返回临时列表并开始一个新的列表。

当它们具有的1差你的阵列元件连接:

var results = source.GroupConnected((a,b) => b - a == 1);