从List中删除具有重复属性的对象

Bax*_*ter 45 c# arrays

我有一个C#中的对象列表.所有对象都包含属性ID.有几个对象具有相同的ID属性.

如何在每个ID属性只有一个对象的情况下修剪List(或创建一个新List)?

[从列表中删除任何其他重复项]

Dan*_*ann 107

如果您想避免使用第三方库,可以执行以下操作:

fooArray.GroupBy(x => x.Id).Select(x => x.First());
Run Code Online (Sandbox Code Playgroud)

这将按Id属性对数组进行分组,然后选择分组中的第一个条目.

  • 这完全适用于我的实现:List <InputRow> uniqueRows = inputRows.GroupBy(x => x.Id).Select(x => x.First()).ToList <InputRow>(); (8认同)
  • 乐意效劳!注意:ToList()上的&lt;InputRow&gt;是多余的。您应该能够执行`.ToList()`。 (2认同)

sll*_*sll 20

MoreLINQ DistinctBy()将完成这项工作,它允许使用object proeprty来实现清晰度.不幸的是,LINQ内置了Distinct()不灵活的enoght.

var uniqueItems = allItems.DistinctBy(i => i.Id);
Run Code Online (Sandbox Code Playgroud)

DistinctBy()

返回给定源的所有不同元素,其中"distinctness"通过投影和投影类型的默认eqaulity比较器确定.

PS:Jon Skeet与社区分享此图书馆的信用

  • 幸运的是,您可以看到它是如何实现的 (2认同)

The*_*ias 13

从 .NET 6 开始,DistinctBy提供了新的 LINQ 运算符:

\n
public static IEnumerable<TSource> DistinctBy<TSource,TKey> (\n    this IEnumerable<TSource> source,\n    Func<TSource,TKey> keySelector);\n
Run Code Online (Sandbox Code Playgroud)\n
\n

根据指定的键选择器函数从序列中返回不同的元素。

\n
\n

使用示例:

\n
List<Item> distinctList = listWithDuplicates\n    .DistinctBy(i => i.Id)\n    .ToList();\n
Run Code Online (Sandbox Code Playgroud)\n

还有一个带有IEqualityComparer<TKey>参数的重载。

\n
\n

就地更新:如果List<T>不需要创建新的,这里是RemoveDuplicates该类的扩展方法List<T>

\n
/// <summary>\n/// Removes all the elements that are duplicates of previous elements,\n/// according to a specified key selector function.\n/// </summary>\n/// <returns>\n/// The number of elements removed.\n/// </returns>\npublic static int RemoveDuplicates<TSource, TKey>(\n    this List<TSource> source,\n    Func<TSource, TKey> keySelector,\n    IEqualityComparer<TKey> keyComparer = null)\n{\n    ArgumentNullException.ThrowIfNull(source);\n    ArgumentNullException.ThrowIfNull(keySelector);\n    HashSet<TKey> hashSet = new(keyComparer);\n    return source.RemoveAll(item => !hashSet.Add(keySelector(item)));\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这个方法很高效(O(n)),但也有点危险,因为它基于潜在破坏性的List<T>.RemoveAll方法\xc2\xb9。如果keySelectorlambda 对某些元素成功,然后对另一个元素失败,则部分修改的List<T>\n既不会恢复到其初始状态,也不会处于可识别为单个Removes 成功的结果的状态。\n相反,它将转换为包含重复出现的现有元素的损坏状态。因此,如果keySelectorlambda 不是防失败的,则应在具有丢弃潜在损坏列表的块的块RemoveDuplicates中调用该方法。trycatch

\n

或者,您可以RemoveAll用安全的自定义实现替换危险的内置函数,该实现提供可预测的行为。

\n

\xc2\xb9对于所有 .NET 版本和平台,包括最新的 .NET 7。我已在 GitHub 上提交了一份提案来记录该方法的损坏行为List<T>.RemoveAll,而我收到的反馈是不应记录该行为,也不应该修复实施。

\n


gdo*_*ica 5

var list = GetListFromSomeWhere();
var list2 = GetListFromSomeWhere();
list.AddRange(list2);

....
...
var distinctedList = list.DistinctBy(x => x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)

More LINQGitHub

或者,如果您由于某种原因不想使用外部dll,可以使用此Distinct重载:

public static IEnumerable<TSource> Distinct<TSource>(
    this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
Run Code Online (Sandbox Code Playgroud)

用法:

public class FooComparer : IEqualityComparer<Foo>
{
    // Products are equal if their names and product numbers are equal.
    public bool Equals(Foo x, Foo 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;

        return x.ID == y.ID
    }
}



list.Distinct(new FooComparer());
Run Code Online (Sandbox Code Playgroud)


小智 5

不确定是否有人仍在寻找其他方法来执行此操作.但我已经使用此代码根据匹配的ID号从User对象列表中删除重复项.

    private ArrayList RemoveSearchDuplicates(ArrayList SearchResults)
    {
        ArrayList TempList = new ArrayList();

        foreach (User u1 in SearchResults)
        {
            bool duplicatefound = false;
            foreach (User u2 in TempList)
                if (u1.ID == u2.ID)
                    duplicatefound = true;

            if (!duplicatefound)
                TempList.Add(u1);
        }
        return TempList;
    }
Run Code Online (Sandbox Code Playgroud)

调用:SearchResults = RemoveSearchDuplicates(SearchResults);

  • 当常规 GroupBy 只是 O(n) 时,这是毫无意义的 O(n ^2)... (2认同)