2

我有一个包含Person这样的模型的列表:

public class Person
{
        [Key]
        public int Id { get; set; }      
        public int Rating1 { get; set; }
        public int Rating2 { get; set; }
        public DateTime CreateDate { get; set; }
}

Rating1从不等于Rating2

问题:

如何获得一个Rating1Rating2等于给定评级值的列表,以及该列表中最后创建的元素?

我通过样本解释我的观点。假设这里是列表:

Rating1    Rating2    CreateDate
4          8          2013-08-15 05:12:00
9          4          2013-08-15 07:12:00
8          4          2013-08-15 08:12:00
5          20         2013-08-15 09:12:00
20         4          2013-08-15 10:12:00
20         5          2013-08-15 11:12:00
4          9          2013-08-15 12:12:00

假设我将评级值“4”作为参数发送到此方法

public IEnumerable<Person> GetList1(int r) {}

并获得一份清单:

8          4          2013-08-15 08:12:00 //because there are many [4 and 8] couples, but this created last.
4          9          2013-08-15 12:12:00 //because there are many [4 and 9] couples, but this created last.
20         4          2013-08-15 10:12:00 //because there is one [4 and 20] couple, this also  created last.

如果我将评级值“20”作为参数发送给 GetList1()方法,我想得到一个列表:

 20         5          2013-08-15 11:12:00 //because there are many [20 and 5] couples, but this created last.
 20         4          2013-08-15 10:12:00 //because there is one [20 and 4] couple, this also  created last.
4

3 回答 3

5

它应该是:

int r = 4; // your rating

var res = from p in lst
          where p.Rating1 == r || p.Rating2 == r
          group p by new { Min = Math.Min(p.Rating1, p.Rating2), Max = Math.Max(p.Rating1, p.Rating2) };

var res2 = res.Select(p => p.OrderByDescending(q => q.CreateDate).First());

我使用Math.MinandMath.Max将最低评分排在第一位,将最大评分排在第二位。所以4, 8相当于8, 4

或者,(或多或少等价):

var res = from p in lst
    where p.Rating1 == r || p.Rating2 == r
    group p by new { Min = Math.Min(p.Rating1, p.Rating2), Max = Math.Max(p.Rating1, p.Rating2) } into q
    select q.OrderByDescending(s => s.CreateDate).First();

或纯 LINQ(但可读性较差)

var res = from p in lst
    where p.Rating1 == r || p.Rating2 == r
    group p by new { Min = Math.Min(p.Rating1, p.Rating2), Max = Math.Max(p.Rating1, p.Rating2) } into q
    select (from s in q orderby s.CreateDate descending select s).First();
于 2013-08-15T15:50:43.907 回答
1

您可以对已排序的两个评级的数组进行分组,以获得具有该唯一评级对的项目。

public IEnumerable<Person> GetList1(IEnumerable<Person> source, int rating) {
    return source.Where(person => person.Rating1 == rating
        || person.Rating2 == rating)
        .GroupBy(person => new int[] { person.Rating1, person.Rating2 }
            .OrderBy(r => r), new SequenceComparer<int>())
        .Select(group => group.OrderByDescending(p => p.CreateDate)
            .First());
}

您需要此比较器才能通过数组的值而不是引用来比较数组GroupBy

public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IEnumerable<T> obj)
    {
        unchecked
        {
            return obj.Take(5).Aggregate(37,
                (acc, item) => acc * 79 + item.GetHashCode());
        }
    }
}

Min请注意,与使用/对值“排序”的答案相比,此答案的主要优势在于Max,它可以有效地扩展到 N 个不同的相关字段。如果您添加 aRating3您需要做的就是将 OR 添加到Whereand 中GroupBy,您就完成了。

于 2013-08-15T15:44:38.940 回答
0
var things=new[] {
  new {Rating1=4,Rating2=8,CreateDate=DateTime.Parse("2013-08-15 05:12:00")},
  new {Rating1=9,Rating2=4,CreateDate=DateTime.Parse("2013-08-15 07:12:00")},
  new {Rating1=8,Rating2=4,CreateDate=DateTime.Parse("2013-08-15 08:12:00")},
  new {Rating1=5,Rating2=20,CreateDate=DateTime.Parse("2013-08-15 09:12:00")},
  new {Rating1=20,Rating2=4,CreateDate=DateTime.Parse("2013-08-15 10:12:00")},
  new {Rating1=20,Rating2=5,CreateDate=DateTime.Parse("2013-08-15 11:12:00")},
  new {Rating1=4,Rating2=9,CreateDate=DateTime.Parse("2013-08-15 12:12:00")}
  };

int r=4;
var result=things
    .Where(t=>t.Rating1==r || t.Rating2==r)
    .GroupBy(t=>new {r1=Math.Min(t.Rating1,t.Rating2),r2=Math.Max(t.Rating1,t.Rating2)},
    (key,group)=>group.OrderByDescending(c=>c.CreateDate).First());

result.Dump();
于 2013-08-15T16:11:40.280 回答