借助bin数组对数组的元素进行分组

时间:2014-11-06 06:02:07

标签: c# linq

假设我们有一个数组:

int[] values = new int[10];
values[0] = 1;
values[1] = 2;
values[2] = 3;
values[3] = 4;
values[4] = 6;
values[5] = 8;
values[6] = 2;
values[7] = 1;
values[8] = 3;
values[9] = 9;

我有另一个数组,比如定义存储桶的def数组:

int[] def= new int[3]; // defs holds the definition of the buckets
def[0] = 0;
def[1] = 5;
def2] = 10;

我想使用这个def数组对values数组进行分组,以便使用c#来获取频率分布:

bin[0] = 7; // the number of array values that lies between 0 and 5
bin[1] = 3; // the number of array values that lies between 5 and 10

我已经找到了一个带循环的解决方案,但我确信有更优雅和更简洁的方法来执行此操作; linq / group by方法。

如何使用LINQ Group By编写此过程?

提前感谢任何有助于答案的人,

艾库特

2 个答案:

答案 0 :(得分:3)

如果我理解正确,那么你看起来像这样:

var array = new[] { 1, 2, 3, 4, 6, 8, 2, 1, 3, 9 };
var buckets = new[] { 0, 5, 10 };
var distributionFreq = buckets
    .Skip(1) // we don't need the first bucket
    .OrderBy(bucket => bucket) // just ensure, that buckets are ordered properly
    .Select((bucket, i) => new
    {
        Min = buckets[i], // minimal value of range
        Max = bucket // maximal value of range
    })
    .Select(range => new
    {
        Range = range,
        NumberOfValuesAtRange = array.Count(item => item > range.Min && item < range.Max)
    })
    .ToArray();

首先,您必须定义值的范围(0..5,5..10等)。 其次,计算源数组中符合范围的值的数量。

请注意,您应该更准确地定义最外层值的条件,例如: 5的值是否适合第一个范围,或第二个范围?

答案 1 :(得分:1)

试试这个:

var bin =
    array
        .GroupBy(x => x / 5)
        .Select(x => x.Count())
        .ToArray();

或者更好的是:

var lookup = array.ToLookup(x => x / 5);
var bin =
    Enumerable
        .Range(0, lookup.Max(x => x.Key) + 1)
        .Select(x => lookup[x].Count())
        .ToArray();

如果原始数组中存在一些异常数字,则第二个示例有效。

甚至更好,使用buckets

var buckets = new [] { 0, 5, 10, };
var lookup = array.ToLookup(x => buckets.Where(b => x >= b).Count() - 1);
var bin =
    Enumerable
        .Range(0, lookup.Max(x => x.Key) + 1)
        .Select(x => lookup[x].Count())
        .ToArray();