C# 区分但忽略空/空
我有一个电影列表,我需要将它们与另一个列表合并并复制 我正在使用Jon Skeet的C# 区分但忽略空/空,c#,linq,morelinq,C#,Linq,Morelinq,我有一个电影列表,我需要将它们与另一个列表合并并复制 我正在使用Jon Skeet的DistinctBy(m=>m.SomeUniqueMovieProperty)来实现这一点,它工作正常。除此之外,我们很快发现,在某些情况下,10-20%的电影(在任一列表中)没有填写此属性,从而导致DistinctBy将它们折叠成一部幸运电影 这是一个问题,我们希望保留所有没有此属性值的电影。最初我想从每个收藏中提取这些电影,复制,然后再合并,有没有一个较短的解决方案 将DistinctBy()的结果与Whe
DistinctBy(m=>m.SomeUniqueMovieProperty)
来实现这一点,它工作正常。除此之外,我们很快发现,在某些情况下,10-20%的电影(在任一列表中)没有填写此属性,从而导致DistinctBy
将它们折叠成一部幸运电影
这是一个问题,我们希望保留所有没有此属性值的电影。最初我想从每个收藏中提取这些电影,复制,然后再合并,有没有一个较短的解决方案 将
DistinctBy()
的结果与Where([null或empty])的结果连接起来。
将
DistinctBy()
的结果与Where([null或empty])的结果连接起来。
如果要包含所有null,则需要将null属性替换为null时唯一的属性。假设属性是字符串,Guid将很好地完成此任务
.DistinctBy(m => m.SomeUniqueMovieProperty ?? Guid.NewGuid().ToString())
任何时候,当它遇到一个空值的属性时,它都会被一个随机的新guid值填充
如果您还希望不删除空标题,请将查询更改为
.DistinctBy(m => String.IsNullOrEmpty(m.SomeUniqueMovieProperty) ? Guid.NewGuid().ToString() : m.SomeUniqueMovieProperty)
另一个选项是通过使您自己的
表现出您想要的方式。这是一个经过调整的版本,仅当shouldApplyFilter
返回true时才应用过滤器,为简洁起见,注释也被删除
static partial class MoreEnumerable
{
public static IEnumerable<TSource> ConditionalDistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter)
{
return source.ConditionalDistinctBy(keySelector, shouldApplyFilter, null);
}
public static IEnumerable<TSource> ConditionalDistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter, IEqualityComparer<TKey> comparer)
{
if (source == null) throw new ArgumentNullException("source");
if (keySelector == null) throw new ArgumentNullException("keySelector");
if (shouldApplyFilter == null) throw new ArgumentNullException("shouldApplyFilter");
return ConditionalDistinctByImpl(source, keySelector, shouldApplyFilter, comparer);
}
private static IEnumerable<TSource> ConditionalDistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter, IEqualityComparer<TKey> comparer)
{
var knownKeys = new HashSet<TKey>(comparer);
foreach (var element in source)
{
var key = keySelector(element);
if (shouldApplyFilter(key) && knownKeys.Add(key))
{
yield return element;
}
}
}
}
如果要包含所有null,则需要将null属性替换为null时唯一的属性。假设属性是字符串,Guid将很好地完成此任务
.DistinctBy(m => m.SomeUniqueMovieProperty ?? Guid.NewGuid().ToString())
任何时候,当它遇到一个空值的属性时,它都会被一个随机的新guid值填充
如果您还希望不删除空标题,请将查询更改为
.DistinctBy(m => String.IsNullOrEmpty(m.SomeUniqueMovieProperty) ? Guid.NewGuid().ToString() : m.SomeUniqueMovieProperty)
另一个选项是通过
使您自己的表现出您想要的方式。这是一个经过调整的版本,仅当shouldApplyFilter
返回true时才应用过滤器,为简洁起见,注释也被删除
static partial class MoreEnumerable
{
public static IEnumerable<TSource> ConditionalDistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter)
{
return source.ConditionalDistinctBy(keySelector, shouldApplyFilter, null);
}
public static IEnumerable<TSource> ConditionalDistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter, IEqualityComparer<TKey> comparer)
{
if (source == null) throw new ArgumentNullException("source");
if (keySelector == null) throw new ArgumentNullException("keySelector");
if (shouldApplyFilter == null) throw new ArgumentNullException("shouldApplyFilter");
return ConditionalDistinctByImpl(source, keySelector, shouldApplyFilter, comparer);
}
private static IEnumerable<TSource> ConditionalDistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, Func<TKey, bool> shouldApplyFilter, IEqualityComparer<TKey> comparer)
{
var knownKeys = new HashSet<TKey>(comparer);
foreach (var element in source)
{
var key = keySelector(element);
if (shouldApplyFilter(key) && knownKeys.Add(key))
{
yield return element;
}
}
}
}
也许您可以在一个复合的独立键上过滤它们,如下所示
movies.DistinctBy(m => String.Format({0}{1}{...},m.prop1,m.prop2,[]));
也许您可以在一个复合的独立键上过滤它们,如下所示
movies.DistinctBy(m => String.Format({0}{1}{...},m.prop1,m.prop2,[]));
最后一种方法,这可能是过度的,你可以实现IEqualityComparer,并把逻辑放在那里,如果NULL被认为是唯一的。DistinctBy仅在这种情况下有一个重载
public class MovieComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
if (x == null || y == null)
{
return false;
}
return x == y;
}
public int GetHashCode(string obj)
{
if (obj == null)
{
return 0;
}
return obj.GetHashCode();
}
}
public-class-MovieComparer:IEqualityComparer
{
公共布尔等于(字符串x、字符串y)
{
如果(x==null | | y==null)
{
返回false;
}
返回x==y;
}
public int GetHashCode(字符串obj)
{
if(obj==null)
{
返回0;
}
返回obj.GetHashCode();
}
}
最后一种方法,这可能是过多的,如果NULL被认为是唯一的,你可以实现IEqualityComparer并把逻辑放在那里。DistinctBy仅在这种情况下有一个重载
public class MovieComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
if (x == null || y == null)
{
return false;
}
return x == y;
}
public int GetHashCode(string obj)
{
if (obj == null)
{
return 0;
}
return obj.GetHashCode();
}
}
public-class-MovieComparer:IEqualityComparer
{
公共布尔等于(字符串x、字符串y)
{
如果(x==null | | y==null)
{
返回false;
}
返回x==y;
}
public int GetHashCode(字符串obj)
{
if(obj==null)
{
返回0;
}
返回obj.GetHashCode();
}
}
假设m
的等于/GetHashCode
未被覆盖,如果m.SomeUniqueMovieProperty
为null
且您没有任何其他唯一键,则可以使用m
本身作为唯一键
DistinctBy(m => (object) m.SomeUniqueMovieProperty ?? m)
假设m
的等于/GetHashCode
未被覆盖,如果m.SomeUniqueMovieProperty
为null
且您没有任何其他唯一键,则可以使用m
本身作为唯一键
DistinctBy(m => (object) m.SomeUniqueMovieProperty ?? m)
我会听从你的选择。过滤掉那些将为null属性值的,在其上运行distinct by,然后将其与过滤后的合并。我会按照您的选择。过滤掉那些将为null属性值的值,在其上运行distinct by,然后将其与过滤后的值合并。您完全忽略了当SomeUniqueMovieProperty等于随机数的字符串表示形式时的情况;)如果该属性可以预测由Guid.NewGuid()
生成的Guid,我认为它应该被过滤掉,这太危险了,它是心理的;)不是吹毛求疵,只是想提醒op在title@MrAnderson我认为标题可能会被干扰为“DistinctBy,但忽略null/empty,只包含所有内容”@MrAnderson,如果:)您完全忽略了某些UniqueMovieProperty等于随机数的字符串表示形式的情况;),我建议您远离gaming.stackexchange.com如果该属性可以预测由Guid.NewGuid()
生成的Guid,我认为它应该被过滤掉,这太危险了,它是心理的;)不是吹毛求疵,只是想提醒op在title@MrAnderson我认为标题可能会被干扰为“DistinctBy,但忽略null/empty,只包含所有内容”@MrAnderson此外,我建议您远离gaming.stackexchange.com,如果:)+1个有趣的想法,不幸的是,该属性是唯一一个足以确定唯一性的可靠属性。如果你认为这是可靠的;)+我有一个有趣的想法,不幸的是,属性是唯一一个足以确定唯一性的可靠属性。如果你称之为可靠;)这个属性的值可能是空的,所以这个解决方案会占便宜。Scott的解决方案可以与什么一起使用?但可读性变差了+1到他的解决方案,也可能在另一种情况下工作此解决方案的一个缺点是它会导致对allMovies
的多个枚举,我们可能会有空值