2014-03-07 69 views
4

我有兩個屬性,A和B的一組對象我想獲得A的Min和B.獲取最大和最小單一LINQ查詢

的最大
var minA = objects.Min(o => o.A); 
var maxB = objects.Max(o => o.B); 

使用LINQ查詢語法,有沒有辦法做到這一點,所以它只能通過設置一次?

期望中的結果將是一個匿名類型(例如,results.MinA = X,results.MaxB = Y)

+1

你爲什麼不寫,通過對象範圍散步一次,並返回一個元組''什麼自己的擴展方法是什麼? – mvo

+0

這很接近猜測,所以我很抱歉,但是在一次傳球時獲得分鐘和馬茲就是這樣的:如果num> max,那麼max。否則如果num

回答

7

最小值和最大值都聚集。一般的LINQ聚合函數是Aggregate

假設屬性的是一個整數,而B是一個字符串,你可以寫這樣的事情:

objects.Aggregate(
    new { 
     MinA = int.MaxValue, 
     MaxB = string.Empty 
    }, 
    (accumulator, o) => new { 
     MinA = Math.Min(o.A, accumulator.MinA), 
     MaxB = o.B > accumulator.MaxB ? o.B : accumulator.MaxB 
    }); 
+0

當然,我忘記了在c#中字符串沒有'>'運算符,但它只是爲了說明。 – Cirdec

+0

您能否確認該集合僅被重複*一次*? – cyrus

+1

是的;我無法想象通過多次迭代實現Aggregate的方法。從文檔:「此方法通過調用func一次爲源中的每個元素。」 – Cirdec

-3

像這樣的事情會爲你工作 我以前的答案沒有工作,

我回去,並嘗試了不同的答案在這裏,結束了這個解決方案,以前

 var values = new List<int> {1, 2, 3, 4, 5}; 

     var maxmin = new {min = values.Min(), max = values.Max()}; 
+0

與非優化解決方案完全沒有區別。 – Migol

+0

它實際上並不工作,因爲'o'不是'IEnumerable'等,因此不具有'Min'或'Max'功能。因此它不會構建'let min = o.Min'(o => oA)' –

1

建議您可以使用Aggregate方法。

var res = new { Min = objects[0].A, Max = objects[0].B } 
var res = objects.Aggregate(res, (r, curr) => r.Min = r.Min < curr.A ? r.Min : curr.A; r.Max = r.Max > curr.B ? r.Max : curr.B); 
+0

這個問題要求提供「LINQ查詢語法」(與lambda擴展方法相反)......不確定這是否重要cyrus與否。 –

+0

@MattTester我認爲他想先單通,查詢方式第二, – Migol

+0

是的,得到我的投票。通過語法糖工作,高效的代碼。 –

0

您可以使用YourObject作爲結果的容器,並使用Math.MinMath.Max整理的語法:

var maxmin = objects.Aggregate(objects[0], (i, j) => 
      new YourObject { A = Math.Min(i.A, j.A), B = Math.Max(i.B, j.B) }); 
4

我知道你想LINQ查詢,但我可以」不要停止指出非linq版本可能更多可讀。比較:

IEnumerable<Message> messages = SomeMessages(); 

Func<DateTime, DateTime, DateTime> min = (dt1, dt2) => dt1 > dt2 ? dt2 : dt1; 
Func<DateTime, DateTime, DateTime> max = (dt1, dt2) => dt1 > dt2 ? dt1 : dt2; 

// linq version 
var result = messages.Aggregate(
    new { StartDate = DateTime.MaxValue, EndDate = DateTime.MinValue }, /* initial value */ 
    (accumulate, current) => new { StartDate = min(accumulate.StartDate, current.ReceivedTime), EndDate = max(accumulate.EndDate, current.ReceivedTime) }); 

// non-linq version 
DateTime start = DateTime.MaxValue; 
DateTime end = DateTime.MinValue; 
foreach (DateTime dt in messages.Select(msg => msg.ReceivedTime)) 
{ 
    start = min(start, dt); 
    end = max(end, dt); 
} 
+0

LINQ版本更具可讀性,因爲當您讀取源代碼時,您不必回頭引用變量和其他需要跟蹤的狀態。當代碼正在轉換數據時,您的眼睛會追隨數據轉換的地方。這就像一本書裏的故事......你從左到右,上下左右看。 – zumalifeguard