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 个值,假设它们现在是整数。

我想要的是拥有

List<List<object>>

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

4

4 回答 4

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);
于 2012-07-26T14:02:07.720 回答
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()
于 2012-07-26T13:56:59.260 回答
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);
}
于 2012-07-26T14:13:52.417 回答
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");
}
于 2012-07-26T16:04:33.077 回答