2014-08-27 115 views
0

我有以下代碼:LINQ排序依據是不工作

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace OrderByElementSubelement 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Place> places = new List<Place>(); 
      places.Add(new Place { Address = "Fifth Street", Score = 29, Houses = new List<House> { new House { Owner = "Mike", Score = 32 }, new House { Owner = "Bobby", Score = 3 } } }); 
      places.Add(new Place { Address = "Sixth Street", Score = 29, Houses = new List<House> { new House { Owner = "Mike", Score = 42 }, new House { Owner = "Ted", Score = 45 } } }); 
      places.Add(new Place { Address = "Seventh Street", Score = 29, Houses = new List<House> { new House { Owner = "Randy", Score = 84 }, new House { Owner = "William", Score = 1 } } }); 
      var placesWithMikesHouseOrderedByMikesHouseScore = places.Where(x => x.Houses.Where(y => y.Owner == "Mike").Count() > 0).OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score)).ToList(); 
     } 

     public class Place 
     { 
      public string Address { get; set; } 
      public int Score { get; set; } 
      public List<House> Houses { get; set; } 
     } 

     public class House 
     { 
      public string Owner { get; set; } 
      public int Score { get; set; } 
     } 
    } 
} 

它拋出該異常:

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll 

Additional information: At least one object must implement IComparable. 

我想查詢由麥克的房子的得分在有序與麥克的家的地方地點(你可以從上面看到這個想法)。一個地方有一個房屋清單。 重要提示:您可以假設沒有個人所有者可以在每個地方擁有多個房屋!

爲什麼它希望一個對象在這裏實現IComparable,我該如何使這個查詢工作?

回答

8

OrderBy函數返回一個集合,而不是一個單一的元素:

OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score)) 

您將需要限制它只是分數,而不是一個IEnumerable<double>(如果Scoredouble),即:

OrderBy(x => x.Houses.First(y => y.Owner == "Mike").Score) 

請注意,如果沒有"Mike"作爲所有者的房屋,則會拋出此問題,但是,您的第一個過濾器應該處理該問題。

+0

非常感謝,裏德! – Alexandru 2014-08-27 20:46:25

3

這裏,我已經剪掉了只是你OrderBy條款:

OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score)) 

您的問題是,即使x.Houses.Where().Select()只有一個元素,它仍然會返回一個IEnumerable不執行IComparable而不是有效的排序。

你想只集合中選擇第一項,所以你有幾個選擇:

OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score).Single()) 
OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score).SingleOrDefault()) 
OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score).First()) 
OrderBy(x => x.Houses.Where(y => y.Owner == "Mike").Select(z => z.Score).FirstOrDefault()) 

每一個都有不同的行爲如果集合包含多個元素和相同行爲,如果它只包含一個元素。

1

裏德的回答類似

var foo = places.Where(p => p.Houses.Any(h => h.Owner == "Mike")) 
       .OrderBy(p => p.Houses.Single(h => h.Owner == "Mike").Score); 

(正切:你的第一個凡()計數> 0應該可能只是一個任何()

至於其他的答案已經指出, OrderBy只需要提供分數。或者,您可以使用make your House class implement IComparable來讓您直接對房屋進行排序。

如果你的要求是Mike只在一個地方擁有一間房子,那麼你可能希望在某個地方獲得Mike所有房屋的最佳分數,在這種情況下,你可以調整爲如下所示。 。

.OrderBy(p => p.Houses.Where(h => h.Owner == "Mike").Max(h => h.Score)); 

(約排序依據VS OrderByDescending和最大邏輯VS閔沒有真正考慮)