将列表分组为3个组,并选择每个组的最大值

时间:2012-07-26 13:45:32

标签: c# linq linq-group

我有一个动态列表列表,目前正在通过它进行过滤:

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

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

我在每个内部列表中都有86000个值。

我需要做的是将值组合成3个组,选择该组的最大值,然后将其插入另一个动态列表列表中,或者只将其从CPUDataIWant中过滤掉。< / p>

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

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>>

在此列表中,我将列出X个名为A的列表。 在A中我将有86000个值,让我们说它们现在是整数。

我想要的是

List<List<object>>

但是A中没有86000个值,我想要28700,这将取自A中每3个值的最大值。

4 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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);

答案 2 :(得分:0)

老式的做事方式使其变得非常简单(虽然它不像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);
}

答案 3 :(得分:0)

如果您觉得需要使用Aggregate,可以这样做:

(用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");
}