我有一个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属性对数组进行分组,然后选择分组中的第一个条目.
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与社区分享此图书馆的信用
The*_*ias 13
从 .NET 6 开始,DistinctBy提供了新的 LINQ 运算符:
public static IEnumerable<TSource> DistinctBy<TSource,TKey> (\n this IEnumerable<TSource> source,\n Func<TSource,TKey> keySelector);\nRun Code Online (Sandbox Code Playgroud)\n\n\n根据指定的键选择器函数从序列中返回不同的元素。
\n
使用示例:
\nList<Item> distinctList = listWithDuplicates\n .DistinctBy(i => i.Id)\n .ToList();\nRun Code Online (Sandbox Code Playgroud)\n还有一个带有IEqualityComparer<TKey>参数的重载。
就地更新:如果List<T>不需要创建新的,这里是RemoveDuplicates该类的扩展方法List<T>:
/// <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}\nRun Code Online (Sandbox Code Playgroud)\n这个方法很高效(O(n)),但也有点危险,因为它基于潜在破坏性的List<T>.RemoveAll方法\xc2\xb9。如果keySelectorlambda 对某些元素成功,然后对另一个元素失败,则部分修改的List<T>\n既不会恢复到其初始状态,也不会处于可识别为单个Removes 成功的结果的状态。\n相反,它将转换为包含重复出现的现有元素的损坏状态。因此,如果keySelectorlambda 不是防失败的,则应在具有丢弃潜在损坏列表的块的块RemoveDuplicates中调用该方法。trycatch
或者,您可以RemoveAll用安全的自定义实现替换危险的内置函数,该实现提供可预测的行为。
\xc2\xb9对于所有 .NET 版本和平台,包括最新的 .NET 7。我已在 GitHub 上提交了一份提案来记录该方法的损坏行为List<T>.RemoveAll,而我收到的反馈是不应记录该行为,也不应该修复实施。
var list = GetListFromSomeWhere();
var list2 = GetListFromSomeWhere();
list.AddRange(list2);
....
...
var distinctedList = list.DistinctBy(x => x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)
More LINQ在GitHub
或者,如果您由于某种原因不想使用外部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);
| 归档时间: |
|
| 查看次数: |
50162 次 |
| 最近记录: |