0

我有一个包含字符串子列表的对象列表,这些结构可以在几天之间更改,我希望比较它们以查看是否进行了更改。

public class Recipe
{
    public string ID { get; set; }
    public string Name { get; set; }
    public List<string> Ingredients { get; set; }
} 

ID字段在列表的版本之间是相同的,Ingredients只是一个字符串列表。

List<Recipe> list1 = GetRecipes("2013-06-20");
List<Recipe> list2 = GetRecipes("2013-06-21");

我试图找到所有Recipe在几天之间发生成分变化的 s。我已经能够想出一个 Linq 语句来查找在list2中但不是list1中的new Recipes

var newRecipes = list1.Where(x => !list2.Any(x1 => x1.ID == x.ID))
    .Union(list2.Where(x => !list1.Any(x1 => x1.ID == x.ID)));

但是,我还没有弄清楚如何只选择在列表之间Recipe发生变化的 s 。Ingredient

var modifiedRecipes = list1.Where(x => !list2.Any(x1 => x1.ID == x.ID && x1.Ingedients.SequenceEqual(x.Ingedients)))
    .Union(list2.Where(x => !list1.Any(x1 => x1.ID == x.ID && x1.Ingedients.SequenceEqual(x.Ingedients))));

如何获取在字符串子列表中发生更改的对象列表?

4

2 回答 2

3

此代码将为您提供相同 ID 的每个不匹配的接收对。但是,您必须对 SequenceEqual 的成分列表进行排序才能起作用。

var changed = from older in GetRecipes("2013-06-20")
              join newer in GetRecipes("2013-06-21") on older.ID equals newer.ID
              where !older.Ingredients.SequenceEquals(newer.Ingredients)
              select new { older, newer };
于 2013-06-21T22:09:57.213 回答
2

当然,您可以这样做。首先获取MoreLINQ(没有它也可以完成,但是效率稍低,请问您是否想要它)。但是,在此之前我们需要添加一个更好的 enumerable IEqualityComparer

public class EnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public void Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return x.SequenceEqual(y);
    }
    public int GetHashCode(IEnumerable<T> obj)
    {
        int x = 31;
        foreach (T element in obj)
        {
            x += 37 * element.GetHashCode();
        }
        return x;
    }
}

之后它就像这样简单:

var modifiedRecipes = list2.ExceptBy(list1, n => n.Ingredients,
    new EnumerableComparer<string>());

如果你打算在你的代码中使用它,我不会一直实例化一个新的 EnumerableComparer,因为它们都是一样的。对每种类型使用相同的实例。

于 2013-06-21T21:53:15.880 回答