如何解决使用 Linq 创建存储桶
我想在 List<double>
上创建 buckets,例如分成 n
个组,例如:
List<double> list = new List<double>() {
0,0.1,1.1,2.2,3.3,4.1,5.6,6.3,7.1,8.9,9.8,9.9,10
};
n = 5
我想得到这样的东西
bucket values
---------------------------------
[0 .. 2] -> {0,1.1}
[2 .. 4] -> {2.2,3.3}
...
[8 .. 10] -> {8.9,10}
问题是如果我使用以下方法执行 GroupBy
:
return items
.Select((item,inx) => new { item,inx })
.GroupBy(x => Math.Floor(x.item / step))
.Select(g => g.Select(x => x.item));
我总是得到不需要的第一个或最后个存储桶,例如[10 .. 12]
(注意所有值都在{{1 }} 范围)或 [0 .. 10]
(注意存储桶的错误范围),其中仅包含极端值([0 .. 0]
或 0
在上面的例子中)。
有什么帮助吗?
解决方法
好吧,对于任意列表,您必须计算范围:[min..max]
然后
step = (max - min) / 2;
代码:
// Given
List<double> list = new List<double>() {
0,0.1,1.1,2.2,3.3,4.1,5.6,6.3,7.1,8.9,9.8,9.9,10
};
int n = 5;
// We compute step
double min = list.Min();
double max = list.Max();
double step = (max - min) / 5;
// And,finally,group by:
double[][] result = list
.GroupBy(item => (int)Math.Clamp((item - min) / step,n - 1))
.OrderBy(group => group.Key)
.Select(group => group.ToArray())
.ToArray();
// Let's have a look:
string report = string.Join(Environment.NewLine,result
.Select((array,i) => $"[{min + i * step} .. {min + i * step + step,2}) : {{{string.Join("; ",array)}}}"));
Console.WriteLine(report);
结果:
[0 .. 2) : {0; 0.1; 1.1}
[2 .. 4) : {2.2; 3.3}
[4 .. 6) : {4.1; 5.6}
[6 .. 8) : {6.3; 7.1}
[8 .. 10) : {8.9; 9.8; 9.9; 10}
请注意 Math.Clamp
方法以确保组键的 [0..n-1]
范围。如果你想要一个 Dictionary<int,double[]>
,其中 Key
是桶的索引:
Dictionary<int,double[]> buckets = list
.GroupBy(item => (int)Math.Clamp((item - min) / step,n - 1))
.ToDictionary(group => group.Key,group => group.ToArray());
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。