2017-10-05 298 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);