简体   繁体   English

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

[英]Compare a property of an object in 2 lists

I have the following (simplified) class: 我有以下(简体)类:

public class CareRate {

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

I would like to compare two lists of CareRate only by their DayRate ; 我只想通过DayRateCareRate比较两个列表; one with CareRates containing the current DayRates and one with CareRates containing the DayRates to update. 一个与CareRates包含当前DayRates和一个与CareRates含有DayRates更新。 Other properties which might have changed like Description, should not be taken into account. 其他可能已更改的属性(例如“描述”)也不应考虑在内。

// 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;
}

The manner to filter the changed CareRate objects by Dayrate , feels a bit devious. 通过Dayrate过滤更改的CareRate对象的Dayrate感觉有些不正确。 I think I am overlooking something. 我想我正在忽略一些东西。 What other and better options are there for acquiring the above? 还有什么其他更好的选择来获取上述内容?

Simply use Zip method in LINQ: 只需在LINQ中使用Zip方法:

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

I think, you can use something like this: 我认为,您可以使用以下方式:

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

Or in one line: 或一行:

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

You can use this: 您可以使用此:

return (from up in updatedCareRates
            join cur in currentCareRates
            on up.Id equals cur.Id
            where up.DayRate != cur.DayRate
            select up).ToList();

Here is one of the rare cases where I think Query syntax is better than Method syntax. 这是我认为查询语法比方法语法更好的少数情况之一。

Instead of using an Where(x => x...) , I looked for a solution with using the Except method as posted here . 我没有使用Where(x => x...) ,而是使用此处发布的Except方法寻找解决方案。

I created a class DayRateComparer as showed below. 我创建了一个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(); 
    }
}

And I used the DayRateComparer like this: 我像这样使用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();
}

I don't like the use of a temporary list (like actualUpdatedCareRates ) and this is not necessary anymore when using a comparer. 我不喜欢使用临时列表(例如actualUpdatedCareRates ),并且在使用比较器时不再需要此列表。 The Zip method as mentioned by @S.Akbari is also a clean and short way but looks a bit complex for me at first sight. @ S.Akbari提到的Zip方法也是一种简洁的方法,但是乍一看对我来说有点复杂。 Thanks all for your posts. 感谢所有您的帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM