我有一个包含字符串子列表的对象列表,这些结构可以在几天之间变化,我希望比较它们以查看是否进行了更改。
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
个天数之间的成分变化。我已经能够提出一个Linq语句来查找 list2 中的新Recipe
但不是 list1 这样的
var newRecipes = list1.Where(x => !list2.Any(x1 => x1.ID == x.ID))
.Union(list2.Where(x => !list1.Any(x1 => x1.ID == x.ID)));
但是,我还没有想出如何仅选择列表之间发生Recipe
更改的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))));
如何获取字符串子列表中已更改的对象列表?
答案 0 :(得分: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 };
答案 1 :(得分:2)
当然,你可以做到这一点。首先获得MoreLINQ(没有它可以完成,但效率稍低,请问我是否需要它)。但是,在此之前我们需要添加更好的可枚举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,因为它们都是一样的。对每种类型使用相同的实例。