假设我们有一个数组:
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编写此过程?
提前感谢任何有助于答案的人,
艾库特
答案 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();