将列表分组为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>>

在这个列表中,我将有X个列表,称为A。在A中,我有86000个值,假设它们现在是int。

我想要的是

List<List<object>>

但是,我想要的不是A中的86000个值,而是28700个,这将由A中每3个值的最大值组成。

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

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

这应该会给出所需的结果:

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

如果你觉得有必要使用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");
}

相关内容

  • 没有找到相关文章