VB.NET按Column14分组累计后降序排序实现帕累托图问题咨询
问题说明
需要实现按Column14的ID对表格数值做分组累计,现有分组累计逻辑可正常运行,但遍历输出的结果顺序混乱,需要将累计结果按降序排列以适配帕累托(Pareto)分析场景。
原有实现代码
Dim chartValues = New Dictionary(Of String, Decimal)() For Each row In DataGridView1.Rows.OfType(Of DataGridViewRow) Dim column14Value = row.Cells().Item("Column14").Value.ToString() Dim column11Value = row.Cells().Item("Column11").Value If (chartValues.ContainsKey(column14Value)) Then chartValues(column14Value) = chartValues(column14Value) + column11Value Else chartValues.Add(column14Value, column11Value) End If Next For Each chartValue In chartValues Dim Tot As Decimal Tot += chartValue.Value ComboBox1.Items.Add(Tot) Next
问题根因
- 常规
Dictionary(Of String, Decimal)不会存储键值对的排序规则,遍历输出的顺序和数值大小、插入顺序无稳定关联,无法直接输出有序结果。 - 帕累托累计逻辑存在错误:累计总和变量
Tot声明在遍历循环内部,每次循环都会被重置为0,实际添加到下拉框的是单个分组的独立值,并非逐组累加的累计值。
修复后实现
直接在分组累计完成后,对字典键值对按单组累计值做降序排序,再遍历排序后的序列计算帕累托累计值:
Dim chartValues = New Dictionary(Of String, Decimal)() For Each row In DataGridView1.Rows.OfType(Of DataGridViewRow) ' 跳过DataGridView的新增空行、空值行,避免运行报错 If row.IsNewRow Then Continue For Dim column14Value = row.Cells("Column14").Value?.ToString() If String.IsNullOrWhiteSpace(column14Value) Then Continue For Dim column11Value = Convert.ToDecimal(row.Cells("Column11").Value) If chartValues.ContainsKey(column14Value) Then chartValues(column14Value) += column11Value Else chartValues.Add(column14Value, column11Value) End If Next ComboBox1.Items.Clear() ' 累计总和变量移到循环外部,初始值为0 Dim Tot As Decimal = 0 ' 按单组累计值降序排序后再遍历计算累计值 For Each groupItem In chartValues.OrderByDescending(Function(kv) kv.Value) Tot += groupItem.Value ComboBox1.Items.Add(Tot) Next
补充:如果后续需要计算帕累托累计占比,可先计算全部分组的总值
Dim grandTotal = chartValues.Values.Sum(),循环内通过Tot / grandTotal即可得到对应位置的累计占比。
内容的提问来源于stack exchange,提问作者Maho Lau
相关产品推荐
相关产品推荐

