2012-07-26 28 views
3

我有當前正通過該過濾的動態的列表的列表的選擇最大:組列表成3組,每組

var CPUdataIWant = from s in rawData 
        where s.stat.Contains("CPU") 
        select s; 

//CPUDataIWant is a List<List<dynamic>>. 

我在每個內部列表86000倍的值。

我需要做的是將這些值分組到3個組中,選擇該組的最大值,然後將其插入到動態列表的另一個列表中,或者只是將其從CPUDataIWant中過濾出來。

所以我想要的一個例子是:

Raw data = 14,5,7,123,5,1,43,87,9 

我的加工值將是:

ProceData = [14,5,7], [123,5,1], [43,87,9] 
ProceData = [14,123,87] 

不具有使用LINQ的,但卻越容易越好。

編輯:好吧,我解釋了什麼想要有點不好。

這裏就是我有:

List<List<object>> 

在這份名單中,我會列出稱爲A. 在一個我會86000個數值X量,讓我們說他們是整數現在。

我想要什麼,是有

List<List<object>> 

但在一個不是86000米的價值觀,我想28700,這會從每3個值的最大值在A.進行

+1

來吧,這很容易。以三個步驟重複收集。檢查我,我+ 1,我+ 2,挑選最大的。添加一些邊界檢查。 Finished ... – DHN 2012-07-26 13:49:56

+1

你能否詳細說一下,R​​awData如何可以是14,5,7,123,5,1,43,87,9?!你不是說這是列表清單嗎? – Vitaliy 2012-07-26 14:12:28

+0

好問題,我是基於'data'的例子來回答我的問題。 – phant0m 2012-07-26 14:13:43

回答

0

這應該得到期望的結果:

var data = new List<dynamic> { 1, 2, 3, 3, 10, 1, 5, 2, 8 }; 
var firsts = data.Where((x, i) => i % 3 == 0); 
var seconds = data.Where((x, i) => (i + 2) % 3 == 0); 
var thirds = data.Where((x, i) => (i + 1) % 3 == 0); 
var list = firsts.Zip(
    seconds.Zip(
     thirds, (x, y) => Math.Max(x, y) 
    ), 
    (x, y) => Math.Max(x, y) 
).ToList(); 

列表現在包含:

3, 10, 8 

或者推廣到一個擴展方法:

public static IEnumerable<T> ReduceN<T>(this IEnumerable<T> values, Func<T, T, T> map, int N) 
{ 
    int counter = 0; 
    T previous = default(T); 
    foreach (T item in values) 
    { 
     counter++; 
     if (counter == 1) 
     { 
      previous = item; 
     } 
     else if (counter == N) 
     { 
      yield return map(previous, item); 
      counter = 0; 
     } 
     else 
     { 

      previous = map(previous, item); 
     } 
    } 

    if (counter != 0) 
    { 
     yield return previous; 
    } 
} 

像這樣來使用:

data.ReduceN(Math.Max, 3).ToList() 
+0

這可能會很慢。 – Hogan 2012-07-26 14:47:55

+0

@霍根:你能澄清一下爲什麼?它在〜80ms內運行100萬個元素,包括轉換爲列表。 – phant0m 2012-07-26 15:01:11

+0

第一個例子(我發表評論時唯一的代碼)運行在O(3n)而不是O(n),我沒有看第二個。 – Hogan 2012-07-26 15:58:53

0
IEnumerable<int> filtered = raw.Select((x, i) => new { Index = i, Value = x }). 
    GroupBy(x => x.Index/3). 
    Select(x => x.Max(v => v.Value)); 

,或者,如果您打算更頻繁地使用它

public static IEnumerable<int> SelectMaxOfEvery(this IEnumerable<int> source, int n) 
{ 
    int i = 0; 
    int currentMax = 0; 
    foreach (int d in source) 
    { 
     if (i++ == 0) 
      currentMax = d; 
     else 
      currentMax = Math.Max(d, currentMax); 
     if (i == n) 
     { 
      i = 0; 
      yield return currentMax; 
     } 
    } 
    if (i > 0) 
     yield return currentMax; 
} 

//... 

IEnumerable<int> filtered = raw.SelectMaxOfEvery(3); 
+0

爲什麼所有的嵌套選擇? ....'GroupBy(x => x.Index/3).Select(x => x.Max(v => v.Value))' – 2012-07-26 14:08:47

+0

我懷疑這會工作,動態我懷疑內容會缺乏'IComparable'。 – Alex 2012-07-26 14:11:46

+0

@BobVale - 沒錯,那是我建立結果的遺留物。更新 – voidengine 2012-07-26 16:19:23

0

OLD-學校的做事方式使其變得非常簡單(儘管它不像LINQ那麼緊湊):

// Based on this spec: "CPUDataIWant is a List<List<dynamic>>" 
// and on the example, which states that the contents are numbers. 
// 
List<List<dynamic>> filteredList = new List<List<dynamic>>(); 
foreach (List<dynamic> innerList in CPUDataIWant) 
{ 
    List<dynamic> innerFiltered = new List<dynamic>(); 

    // if elements are not in multiples of 3, the last one or two won't be checked. 
    for (int i = 0; i < innerList.Count; i += 3) 
    { 
     if(innerList[i+1] > innerList[i]) 
      if(innerList[i+2] > innerList[i+1]) 
       innerFiltered.Add(innerList[i+2]); 
      else 
       innerFiltered.Add(innerList[i+1]); 
     else 
      innerFiltered.Add(innerList[i]); 
    } 
    filteredList.Add(innerFiltered); 
} 
0

如果你覺得有必要使用聚合,你可以做這樣的:

(室內用LinqPad測試)

class Holder 
{ 
     public dynamic max = null; 
     public int count = 0; 
} 

void Main() 
{ 
    var data = new List<dynamic> 
     {new { x = 1 }, new { x = 2 }, new { x = 3 }, 
     new { x = 3 }, new { x = 10}, new { x = 1 }, 
     new { x = 5 }, new { x = 2 }, new { x = 1 }, 
     new { x = 1 }, new { x = 9 }, new { x = 3 }, 
     new { x = 11}, new { x = 10}, new { x = 1 }, 
     new { x = 5 }, new { x = 2 }, new { x = 12 }}; 

    var x = data.Aggregate(
     new LinkedList<Holder>(), 
     (holdList,inItem) => 
     { 
      if ((holdList.Last == null) || (holdList.Last.Value.count == 3)) 
      { 
      holdList.AddLast(new Holder { max = inItem, count = 1}); 
      } 
      else 
      { 
      if (holdList.Last.Value.max.x < inItem.x) 
       holdList.Last.Value.max = inItem; 

      holdList.Last.Value.count++; 
      } 
      return holdList; 
     }, 
     (holdList) => { return holdList.Select((h) => h.max);}); 

    x.Dump("We expect 3,10,5,9,11,12"); 
}