c# - 使用 Linq 创建存储桶
问题描述
我想在诸如以下组中创建存储桶:List<double>
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, 0.1, 1.1}
[2 .. 4] -> {2.2, 3.3}
...
[8 .. 10] -> {8.9, 9.8, 9.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]
(注意所有值都在[0 .. 10]
范围内)或[0 .. 0]
(注意存储桶的错误范围)仅包含极值(0
或10
在上面的示例中)。
任何帮助?
解决方案
好吧,对于任意列表,您必须计算 range:[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, 0, 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, 0, n - 1))
.ToDictionary(group => group.Key, group => group.ToArray());
推荐阅读
- javascript - 使用 Electron 在 Windows 上获取名字和姓氏
- java - 从 ipcam 播放音频流的极端延迟
- java - 是否可以在使用动态包含时从另一个 JSP 调用方法?
- python - 通过批处理文件运行时,将 python 脚本的输出打印到 Windows 控制台
- python - Pandas 根据日期范围和另一列过滤数据框
- html - 从 React 中的隐藏溢出中弹出
- facebook-graph-api - 获取给定日期的 Instagram 关注者数量
- r - 为什么 r 中关于生成 Gamma 随机变量的代码不返回预期的输出?
- cross-browser - 我应该如何做跨浏览器解决方案?
- powershell - 如何使用 powershell 传递参数?