2014-08-27 87 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闵没有真正考虑)