簡體   English   中英

c#linq查詢數據表以選擇具有重復項的所有最小值

[英]c# linq query on data table to select all minimum values with duplicates

我有一個數據表,如:

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

什么改變讓我得到目標表。

據我所知,你需要:

  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成員是與初始數據相同類型的列表,但如果要對其進行轉換,則可以執行“選擇”。

與您的代碼相比,這里的主要區別是在ChData成員的構造中使用Where()子句(以及使用let子句來計算min)。

編輯:如果您想要一個級別的值列表(而不是列表列表),您可以使用SelectMany:

var plainList = minLPData.SelectMany(g => g.ChData.Select(d => new { ChNo = g.key, ChData = d["ChData"] }));
IEnumerable<DataRow> lowestChNoRows = loadProfileData.AsEnumerable()
            .GroupBy(r => r.Field<double>("ChNo"))
            .OrderBy(g => g.Key)
            .First();

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

DataTable tblLowestChNoRows = lowestChNoRows.CopyToDataTable();

你為什么要分組? 在我看來,你只想要所有列表的最小值。

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"] });
// 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();

結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM