1

我有一个数据表,如:

ChNo     ChData
1         0.1
1         0.2
2         0.0
1         0.1
2         0.2
1         0.1
1         0.1
2         0.0

对于基于 chNO 的最小值,我编写了如下查询

var minLPData = from minData in loadProfileData.AsEnumerable()
                                orderby minData["ChNo"]
                                group minData by minData["ChNo"] into g                                
                                select new
                                {
                                    ChNo = g.Key,
                                    ChData = g.CopyToDataTable().Compute("Min(ChData)", string.Empty)
                                };

但结果我越来越喜欢

ChNo     ChData
1         0.0
2         0.0

我想要基于 ChNo 的所有最小值,包括重复项

ChNo     ChData
1         0.1
1         0.1
1         0.1
1         0.1
2         0.0
2         0.0

什么变化让我得到目标表。

4

4 回答 4

2

据我了解,您需要:

  1. 按渠道对元素进行分组
  2. 找到每个通道的最小值
  3. 查找所有具有此值的元素

所以,我们开始:

var minLPData =
    from data in loadProfileData.AsEnumerable()
    group data by data["ChNo"] into gData
    orderby gData.Key
    let minValue = gData.Min(d => d["ChData"])
    select new
        {
            ChNo = gData.key,
            ChData = gData.Where(d => d["ChData"] == minValue).ToList()
        };

这将为您提供任何匿名类型的枚举。然后,您可以将其转换为字典。匿名类型中的 ChData 成员是一个与初始数据类型相同的列表,但如果要对其进行转换,可以进行 Select。

与您的代码相比,这里的主要区别是在 ChData 成员的构造中使用 Where() 子句(以及使用 let 子句来计算最小值)。

编辑:如果您想要一个级别的值列表(而不是列表列表),您可以使用 SelectMany:

var plainList = minLPData.SelectMany(g => g.ChData.Select(d => new { ChNo = g.key, ChData = d["ChData"] }));
于 2012-10-30T13:39:48.277 回答
1
IEnumerable<DataRow> lowestChNoRows = loadProfileData.AsEnumerable()
            .GroupBy(r => r.Field<double>("ChNo"))
            .OrderBy(g => g.Key)
            .First();

如果你想要一个DataTable具有最低值行的新的:

DataTable tblLowestChNoRows = lowestChNoRows.CopyToDataTable();
于 2012-10-30T12:57:57.120 回答
1

你为什么要分组?在我看来,您只想要所有列表的最小值。

var list = loadProfileData.AsEnumerable().ToList();

// Get the minimum value
var minValue = list.Min(v => v["ChData"]);

// Get all elements that have the same value than the minimum value
// Order them by ChNo
var minimums = list.Where(v => v["ChData"] == minValue).OrderBy(v => v["ChNo"]);

然后,您可以根据需要转换此列表,例如:

var minLPData = minimums.Select(v => new { ChNo = v["ChNo"], ChData = v["ChData"] });
于 2012-10-30T13:02:39.700 回答
0
// Prepare the data
var table = new DataTable();    

// The type must be specified explicitly,
// otherwise it will be string
table.Columns.Add("ChNo", typeof(int));
table.Columns.Add("ChData", typeof(double));

new[]
{
    new {Key = 1, Data = 0.0},
    new {Key = 1, Data = 0.1},
    new {Key = 2, Data = 0.0},
    new {Key = 1, Data = 0.0},
    new {Key = 2, Data = 0.1},
    new {Key = 1, Data = 0.0},
    new {Key = 1, Data = 0.0},
    new {Key = 2, Data = 0.0},
}
.ToList().ForEach(p => table.Rows.Add(p.Key, p.Data));

// Make a projection, so it is easier to work with
var data = table.AsEnumerable().Select(p => 
    new { Key = p["ChNo"], Data = p["ChData"] }).ToArray();

var minValues = data.GroupBy(p => p.Key)
    .ToDictionary(p => p.Key, p => p.Min(i => i.Data));

var res = data.Where(p => minValues[p.Key] == p.Data)
    .OrderBy(p => p.Key)
    .ToArray();

结果

于 2012-10-30T13:18:43.380 回答