【问题标题】:Prevent duplicates from array, based on condition [closed]根据条件防止数组重复[关闭]
【发布时间】:2021-01-22 13:34:25
【问题描述】:

我有一个数字数组,我需要防止重复。对于数组中大于0 的每个数字,我需要删除除一个之外的所有重复项。例如,如果输入为 [0,0,0,1,1,1,1,1,2,2],则输出应为:[0,0,0,1,2]。有人能帮我吗?我已经尝试了下面的代码,但我得到了这样的结果 [0,1,2]。

Results.GroupBy(item => item.id).Select(x => x.First());

输入和预期输出的另一个例子:

Input:  {[id=0,Name="test0"],[id=0,Name="test0"], [id=1,Name="test1"],[id=1,Name="test1"],[id=1,Name="test1"],[id=2,Name="test2"],[id=2,Name="test2"]}
Output: {[id=0,Name="test0"],[id=0,Name="test0"],[id=1,Name="test1"],[id=2,Name="test2"]}

【问题讨论】:

  • @John 我认为他们的意思是他们想要删除重复项 > 0
  • 是的,我预计需要避免 3 个零
  • 您可以对值进行分组,然后根据该值取一个或全部。 list.GroupBy(x => x).SelectMany(grp => grp.Key > 0 ? grp.Take(1) : grp) 请注意,即使它们不像您的示例那样全部排成一行,也会删除重复项。
  • 如果零分布在整个列表中,您希望输出是什么,例如:0, 0, 0, 1, 1, 0, 1, 2, 0, 2, 2, 2, 0

标签: c# .net linq delegates


【解决方案1】:

您可以编写自己的扩展方法,其工作方式类似于内置 LINQ 方法:

public static class Extensions
{
    public static IEnumerable<T> DistinctWhere<T>(this IEnumerable<T> input, Func<T,bool> predicate)
    {
        HashSet<T> hashset = new HashSet<T>();
        foreach(T item in input)
        {
            if(!predicate(item))
            {
                yield return item;
                continue;
            }
            
            if(!hashset.Contains(item))
            {
                hashset.Add(item);
                yield return item;
            }
        }
    }
}

用法是

int[] input = new int[] { 0,0,0,1,1,1,1,1,2,2 };
int[] result = input.DistinctWhere(x => x > 0).ToArray();

在线演示:https://dotnetfiddle.net/QDpCDF

编辑:如果您想使用列表中对象的属性(如 ID 属性),可以对该方法进行一些细微的修改:

public static class Extensions
{
    public static IEnumerable<T> DistinctWhere<T,T2>(this IEnumerable<T> input, Func<T,T2> selector, Func<T2,bool> predicate)
    {
        HashSet<T2> hashset = new HashSet<T2>();
        foreach(T item in input)
        {
            T2 value = selector.Invoke(item);
            if(!predicate.Invoke(value))
            {
                yield return item;
                continue;
            }

            if(!hashset.Contains(value))
            {
                hashset.Add(value);
                yield return item;
            }
        }
    }
}

用法是

TypeWithId[] input = new TypeWithId[]
{
    new TypeWithId { ID = 0 } , 
    new TypeWithId { ID = 0 } , //... also initialize the other items
};
TypeWithId[] result = input.DistinctWhere(x => x.ID, x => x > 0).ToArray();

【讨论】:

  • 看起来 OPs 的项目集合有一个他们正在过滤的 Id 属性,如果他们希望结果是项目而不是 Id,那么如果没有一些更改,这将无法工作,以便它会散列 Id 而不是实际的项目。
  • @juharr:这很容易实现。我添加了一个如何做到这一点的示例。
  • “错误 CS0246 找不到类型或命名空间名称 'T2'(您是否缺少 using 指令或程序集引用?)” Btw 而不是 TT2 我会使用名称TSourceTKey,而不是selecterkeySelector。同样在接受选择器时,可能需要额外的参数IEqualityComparer&lt;TKey&gt; keyComparer
猜你喜欢
  • 1970-01-01
  • 2011-07-06
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-20
相关资源
最近更新 更多