比较2个列表中对象的属性

时间:2017-11-07 13:41:49

标签: c# .net linq linq-to-entities

我有以下(简化)课程:

public class CareRate {

  [Key]
  public int Id { get; set; }
  public string Description { get; set; }
  public decimal DayRate { get; set; }
}

我想仅通过CareRate比较DayRate的两个列表;一个CareRates包含当前DayRates,另一个CareRates包含要更新的DayRates。不应考虑其他可能已更改的属性,如描述。

// Just a test method
public List<CareRate> FilterChangedCareRates(){
    var currentCareRates = new List<CareRate>{
        new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" }, 
        new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" } 
    };

    var updatedCareRates = new List<CareRate>{
        new CareRate { Id = 1, DayRate = 2,22 }, 
        new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
   };

    var actualUpdatedCareRates = new List<CareRate>();

    foreach(var updatedCareRate in updatedCareRates) {
        var currentCareRate = currentCareRates.Single(x => x.Id == updatedCareRate.Id); 
        if (updatedCareRate.DayRate != currentCareRate.DayRate) {
            actualUpdatedCareRates.Add(updatedCareRate); 
        }
    }
    return actualUpdatedCareRates;
}

通过CareRate过滤已更改的Dayrate对象的方式感觉有点狡猾。我想我忽略了一些事情。获得上述内容有哪些其他更好的选择?

4 个答案:

答案 0 :(得分:1)

只需在LINQ中使用Zip方法:

var actualUpdatedCareRates = currentCareRates.Zip(updatedCareRates, 
                             (f, s) => f.DayRate != s.DayRate ? s : null)
                             .Where(c => c != null).ToList();

答案 1 :(得分:0)

我想,你可以使用这样的东西:

updatedCareRates.ForEach(x =>
{
    if (currentCareRates.FirstOrDefault(y => y.Id == x.Id && y.DayRate != x.DayRate) != null)
        actualUpdatedCareRates.Add(x);
});

或者在一行中:

updatedCareRates.Where(x => currentCareRates.FirstOrDefault(y => y.Id == x.Id &&
                            y.DayRate != x.DayRate) != null).ToList()
                           .ForEach(x => actualUpdatedCareRates.Add(x));

答案 2 :(得分:0)

您可以使用:

[{"Id":64629,
   "Name":"XYZ",
  "Transaction":
  [
    { "Id":10 , "Message": "xyz"},
    { "Id":11 , "Message": "xyz1"},
    { "Id":12 , "Message": "xyz2"},
   ]
  }
]

这是我认为查询语法优于方法语法的罕见情况之一。

答案 3 :(得分:0)

我没有使用Where(x => x...),而是使用发布时hereExcept方法寻找解决方案。

我创建了一个类DayRateComparer,如下所示。

public class DayRateComparer : IEqualityComparer<CareRate>
{
    public bool Equals(CareRate x, CareRate y) {
        if (x = null) throw new ArgumentNullException(nameof(x));
        if (y = null) throw new ArgumentNullException(nameof(y));

        return x.Id == y.Id && x.DayRate == y.DayRate;
    }

    public int GetHashCode(CareRate obj) {
        retun obj.Id.GetHashCode() + obj.DayRate.GetHashCode(); 
    }
}

我使用DayRateComparer这样:

// Just a test method
public List<CareRate> FilterChangedCareRates(){
    var currentCareRates = new List<CareRate>{
        new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" }, 
        new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" } 
    };

    var updatedCareRates = new List<CareRate>{
        new CareRate { Id = 1, DayRate = 2,22 }, 
        new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
   };

    return updatedCareRates.Except(currentCareRates, new DayRateComparer()).ToList();
}

我不喜欢使用临时列表(如actualUpdatedCareRates),这在使用比较器时不再需要。 @S.Akbari提到的Zip方法也是一种简洁明了的方法,但对我来说看起来有点复杂。谢谢大家的帖子。