我有一个MongoDB数据库,我在其中存储所有图片,当我检索它们时,我存储了一些双打,这不是很好,但无论如何我只想显示不同的元素。
@foreach (Foto f in fotos.Distinct(new IEqualityComparer<Foto> { )
但是 Foto 类有一个名为 smallurl 的属性,我只想通过这个属性显示不同的元素。那么如何编写一个自定义的IEqualityComparer。
我有一个MongoDB数据库,我在其中存储所有图片,当我检索它们时,我存储了一些双打,这不是很好,但无论如何我只想显示不同的元素。
@foreach (Foto f in fotos.Distinct(new IEqualityComparer<Foto> { )
但是 Foto 类有一个名为 smallurl 的属性,我只想通过这个属性显示不同的元素。那么如何编写一个自定义的IEqualityComparer。
var listOfUrls = fotos.Select(f => f.smallurl).Distinct();
编辑专门回答您的问题
实际上是从 MSDN 文档中复制的,您可以通过搜索 c# IEqualityComparer http://msdn.microsoft.com/en-us/library/ms132151.aspx找到该文档
class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto f1, Foto f2)
{
return f1.smallurl == f2.smallurl;
}
public int GetHashCode(Foto f)
{
return f.smallurl.GetHashCode();
}
}
@foreach (Foto f in fotos.Distinct(new FotoEqualityComparer() )
这实际上很容易。只需为您的方法提供一个独特的选择器,如下所示:
public static IEnumerable<TSource> DistinctBy<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> keySelector)
{
Dictionary<TResult, TSource> seenItems = new Dictionary<TResult, TSource>();
foreach (var item in enumerable)
{
var key = keySelector(item);
if (!seenItems.ContainsKey(key))
{
seenItems.Add(key, item);
yield return item;
}
}
}
或者,您可以创建另一个来为 IEquality 比较器进行通用实现:
public static IEnumerable<TSource> DistinctBy<TSource>(this IEnumerable<TSource> enumerable, Func<TSource, TSource, bool> equalitySelector, Func<TSource, int> hashCodeSelector)
{
return enumerable.Distinct(new GenericEqualitySelector<TSource>(equalitySelector, hashCodeSelector));
}
class GenericEqualitySelector<TSource> : IEqualityComparer<TSource>
{
public Func<TSource, TSource, bool> _equalityComparer = null;
public Func<TSource, int> _hashSelector = null;
public GenericEqualitySelector(Func<TSource, TSource, bool> selector, Func<TSource, int> hashSelector)
{
_equalityComparer = selector;
_hashSelector = hashSelector;
}
public bool Equals(TSource x, TSource y)
{
return _equalityComparer(x, y);
}
public int GetHashCode(TSource obj)
{
return _hashSelector(obj);
}
}
public class MyEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto x, Foto y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the foto's properties are equal.
return x.smallurl == y.smallurl ;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Foto foto)
{
//Check whether the object is null
if (Object.ReferenceEquals(foto, null)) return 0;
//Get hash code for the foto.smallurl field if it is not null.
return foto.smallurl == null ? 0 : foto.smallurl.GetHashCode();
}
}
创建自己的:
public class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto x, Foto y)
{
return x.smallurl.Equals(y.smallurl);
}
public int GetHashCode(Foto foto)
{
return foto.smallurl.GetHashCode();
}
}
并像这样使用它:
fotos.Distinct(new FotoEqualityComparer());
编辑:
.Distinct() 没有内联 lambda 重载,因为当两个对象比较相等时,它们必须具有相同的 GetHashCode 返回值(否则 Distinct 内部使用的哈希表将无法正常工作)。
但是,如果您希望它在一行中,那么您也可以进行分组以达到相同的结果:
fotos.GroupBy(f => f.smallurl).Select(g => g.First());
使用 GroupBy 的代码要简单得多:
@foreach (Foto f in fotos.GroupBy(f => f.smallurl).Select(g => g.First()))
您应该创建自己的 EquilityComparer:
class FotoEqualityComparer : IEqualityComparer<Foto>
{
public bool Equals(Foto b1, Foto b2)
{
if (b1.smallurl == b2.smallurl)
return true;
else
return false;
}
public int GetHashCode(Foto bx)
{
int hCode = bx.smallurl ;
return hCode.GetHashCode();
}
}