我正在尝试从各种查询中维护一个独特模型列表。不幸的是,我们的模型的equals方法没有定义,所以我不能轻易使用哈希映射。
作为快速修复,我使用了以下代码:
public void AddUnique(
List<Model> source,
List<Model> result)
{
if (result != null)
{
if (result.Count > 0
&& source != null
&& source.Count > 0)
{
source.RemoveAll(
s => result.Contains(
r => r.ID == s.ID));
}
result.AddRange(source);
}
}
不幸的是,这不起作用。当我逐步完成代码时,我发现即使我已经检查过以确保Model
和{{1}中至少有一个ID
具有相同的source
},result
行不会更改RemoveAll(Predicate<Model>)
中的项目数。我错过了什么?
答案 0 :(得分:10)
上面的代码甚至不应该编译,因为Contains
需要Model
,而不是谓词。
您可以使用Any()代替:
source.RemoveAll(s => result.Any(r => r.ID == s.ID));
这将正确删除源中的项目。
答案 1 :(得分:1)
我可能会选择以不同的方式解决问题。
你说你在课堂上没有合适的平等实现。也许你不能改变它。但是,您可以定义IEqualityComparer<Model>
实现,该实现允许您指定实际Equals
类本身外部的相应GetHashCode
和Model
实现。
var comparer = new ModelComparer();
var addableModels = newSourceOfModels.Except(modelsThatAlreadyExist, comparer);
// you can then add the result to the existing
您可以将比较器定义为
class ModelComparer : IEqualityComparer<Model>
{
public bool Equals(Model x, Model y)
{
// validations omitted
return x.ID == y.ID;
}
public int GetHashCode(Model m)
{
return m.ID.GetHashCode();
}
}
答案 2 :(得分:0)
source.RemoveAll(source.Where(result.Select(r => r.ID).Contains(source.Select(s => s.ID))));
此语句的目标是制作两个ID枚举,一个用于源,一个用于结果。然后,它将返回两个枚举中每个元素的where语句的true。然后它将删除任何返回true的元素。
答案 3 :(得分:0)
您的代码正在删除两个列表中相同的所有模型,而不是那些具有相同 ID 的模型。除非它们实际上是模型的相同实例,否则它将无法像您期望的那样工作。
有时我会将这些扩展方法用于此类事情:
public static class CollectionHelper
{
public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> selector)
{
var itemsToRemove = list.Where(selector).ToList();
foreach (var item in itemsToRemove)
{
list.Remove(item);
}
}
public static void RemoveWhere<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, bool> selector)
{
var itemsToRemove = dictionary.Where(selector).ToList();
foreach (var item in itemsToRemove)
{
dictionary.Remove(item);
}
}
}