c#linq查询数据表以选择具有重复项的所有最小值

时间:2012-10-30 12:50:57

标签: c# linq datatable

我有一个数据表,如:

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的i-written查询的最小值,如

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 个答案:

答案 0 :(得分:2)

据我所知,你需要:

  1. 按渠道分组您的元素
  2. 查找每个频道的最小值
  3. 查找具有此值的所有元素
  4. 所以,我们走了:

    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成员是与初始数据相同类型的列表,但如果要对其进行转换,则可以执行“选择”。

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

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

    var plainList = minLPData.SelectMany(g => g.ChData.Select(d => new { ChNo = g.key, ChData = d["ChData"] }));
    

答案 1 :(得分:1)

IEnumerable<DataRow> lowestChNoRows = loadProfileData.AsEnumerable()
            .GroupBy(r => r.Field<double>("ChNo"))
            .OrderBy(g => g.Key)
            .First();

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

DataTable tblLowestChNoRows = lowestChNoRows.CopyToDataTable();

答案 2 :(得分: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"] });

答案 3 :(得分: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();

Result