【问题标题】:Create Buckets ith Linq [duplicate]使用 Linq 创建存储桶 [重复]
【发布时间】:2021-03-16 15:28:33
【问题描述】:

我想在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, 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));

我总是得到 unwanted firstlast 存储桶,例如 [10 .. 12](请注意,所有值都在 [0 .. 10] 范围内)或[0 .. 0](注意桶的错误范围),其中仅包含extreme值(上例中的010)。

任何帮助?

【问题讨论】:

  • 所以你有一个列表一本字典?这两件事有什么关系? step 是什么?我完全不明白这个问题。
  • 您能否更详细地说明您所说的“极端值”是什么意思?如果您有任何仅在边缘情况下发生的错误,您应该在您的问题中至少包含其中一种边缘情况。此外,您的问题还不清楚。请尝试在您的描述中提供更多细节
  • 通过什么输入会得到意想不到的输出?该输出是什么?您期望什么?
  • 您在寻找集群吗?en.wikipedia.org/wiki/K-means_clustering。你能用minimal reproducible example 覆盖基本的边缘情况吗?我们是否将 {3.3, 4.1} 归为一组,因为这 2 个之间小于 1?

标签: c# linq grouping bucket


【解决方案1】:

好吧,对于 任意 列表,您必须计算范围:[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&lt;int, double[]&gt;,其中Key 是存储桶的索引:

  Dictionary<int, double[]> buckets = list
    .GroupBy(item => (int)Math.Clamp((item - min) / step, 0, n - 1))
    .ToDictionary(group => group.Key, group => group.ToArray());

【讨论】:

  • 谢谢!第一次使用Math.Clamp方法,很有帮助
猜你喜欢
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 2019-12-27
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 2010-10-23
相关资源
最近更新 更多