.NET?中實(shí)現(xiàn)?List?集合去重的方法
前言
在數(shù)據(jù)處理中,去除集合中的重復(fù)元素是一個(gè)常見(jiàn)的需求。.NET 6 和 .NET 7 引入了 DistinctBy 方法,這是一個(gè)非常實(shí)用的新特性,可以方便地根據(jù)指定的鍵對(duì)集合進(jìn)行去重。
本文將詳細(xì)介紹 DistinctBy 方法的使用,并通過(guò)具體的案例來(lái)展示其在實(shí)際開(kāi)發(fā)中的應(yīng)用。
正文
1、DistinctBy 方法
DistinctBy 方法允許我們?cè)?LINQ 查詢中根據(jù)某個(gè)鍵對(duì)集合中的元素進(jìn)行去重。
這個(gè)方法返回一個(gè)新的集合,其中只包含根據(jù)指定鍵唯一確定的元素。
方法簽名
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
);2、基本用法
最簡(jiǎn)單的用法是在 LINQ 查詢中直接調(diào)用 DistinctBy 方法,然后處理去重后的集合。
說(shuō)明
假設(shè)我們有一個(gè)用戶列表,我們想要根據(jù)用戶名去除重復(fù)的用戶。
using System.Linq;
class User
{
public string Name { get; set; }
public int Age { get; set; }
}
var users = new List<User>
{
new User { Name = "Alice", Age = 25 },
new User { Name = "Bob", Age = 32 },
new User { Name = "Alice", Age = 28 },
new User { Name = "David", Age = 35 }
};
var distinctUsers = users.DistinctBy(user => user.Name);
foreach (var user in distinctUsers)
{
Console.WriteLine($"Name: {user.Name}, Age: {user.Age}");
}輸出結(jié)果:
Name: Alice, Age: 25
Name: Bob, Age: 32
Name: David, Age: 35
過(guò)濾前后元素還是保持原有的順序,我們可以查看源碼。
源碼
private static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
using IEnumerator<TSource> enumerator = source.GetEnumerator();
?
if (enumerator.MoveNext())
{
var set = new HashSet<TKey>(DefaultInternalSetCapacity, comparer);
do
{
TSource element = enumerator.Current;
if (set.Add(keySelector(element)))
{
yield return element;
}
}
while (enumerator.MoveNext());
}
}通過(guò)查看源碼,可以看到是利用了 HashSet 去重,元素順序并未被打亂。
在處理集合時(shí),我們經(jīng)常需要去除重復(fù)的元素,同時(shí)保持原有的順序。
使用 HashSet 可以高效地實(shí)現(xiàn)這一目標(biāo)。
首先將指定的鍵嘗試添加到 HashSet 中,如果添加成功,說(shuō)明該鍵沒(méi)有重復(fù);
如果添加失敗,說(shuō)明已經(jīng)存在相同的鍵,此元素將被過(guò)濾掉。
3、復(fù)雜用法
DistinctBy 方法可以用于更復(fù)雜的去重邏輯,例如根據(jù)多個(gè)屬性進(jìn)行去重。
說(shuō)明
假設(shè)我們有一個(gè)訂單列表,我們想要根據(jù)客戶名稱和訂單金額去除重復(fù)的訂單。
class Order
{
public int OrderId { get; set; }
public string CustomerName { get; set; }
public decimal Amount { get; set; }
}
var orders = new List<Order>
{
new Order { OrderId = 1, CustomerName = "Alice", Amount = 100.0m },
new Order { OrderId = 2, CustomerName = "Bob", Amount = 150.0m },
new Order { OrderId = 3, CustomerName = "Alice", Amount = 100.0m },
new Order { OrderId = 4, CustomerName = "Charlie", Amount = 120.0m },
new Order { OrderId = 5, CustomerName = "Bob", Amount = 150.0m }
};
var distinctOrders = orders.DistinctBy(order => (order.CustomerName, order.Amount));
?
foreach (var order in distinctOrders)
{
Console.WriteLine($"Order ID: {order.OrderId}, Customer: {order.CustomerName}, Amount: {order.Amount}");
}輸出結(jié)果:
Order ID: 1, Customer: Alice, Amount: 100.0
Order ID: 2, Customer: Bob, Amount: 150.0
Order ID: 4, Customer: Charlie, Amount: 120.0
4、性能考慮
DistinctBy 方法在內(nèi)部使用哈希表來(lái)跟蹤已經(jīng)出現(xiàn)的鍵,因此在大多數(shù)情況下性能非常好。但在處理非常大的數(shù)據(jù)集時(shí),仍然需要注意內(nèi)存使用情況。
說(shuō)明
假設(shè)我們有一個(gè)包含數(shù)百萬(wàn)條記錄的大集合,我們需要根據(jù)某個(gè)鍵進(jìn)行去重。
var largeCollection = Enumerable.Range(1, 10000000).Select(i => new { Id = i, Value = i % 1000 });
var distinctLargeCollection = largeCollection.DistinctBy(item => item.Value);
Console.WriteLine($"Distinct count: {distinctLargeCollection.Count()}");5、異步 LINQ 查詢中的使用
DistinctBy 方法也可以在異步 LINQ 查詢中使用,結(jié)合 IAsyncEnumerable<T> 類型,處理大量數(shù)據(jù)時(shí)更加高效。
說(shuō)明
假設(shè)我們有一個(gè)異步方法返回一個(gè)用戶列表,我們想要根據(jù)用戶名去除重復(fù)的用戶。
using System.Net.Http.Json
public async IAsyncEnumerable<User> GetUsersAsync()
{
var response = await httpClient.GetAsync("https://api.example.com/users");
var usersJson = await response.Content.ReadAsStringAsync();
// 使用Json序列化工具解析用戶列表
var users = JsonSerializer.Deserialize<List<User>>(usersJson);
foreach (var user in users)
{
yield return user;
}
}
// 使用異步LINQ查詢
var distinctUsers = await GetUsersAsync().DistinctByAsync(user => user.Name).ToListAsync();
?
foreach (var user in distinctUsers)
{
Console.WriteLine($"Name: {user.Name}, Age: {user.Age}");
}總結(jié)
DistinctBy 方法是 .NET 6 和 .NET 7 中 LINQ 的一個(gè)非常實(shí)用的新特性。我們?cè)?LINQ 查詢中根據(jù)指定的鍵對(duì)集合進(jìn)行去重,簡(jiǎn)化了代碼并提高了開(kāi)發(fā)效率。
希望本文能幫助大家更好地理解和利用 .NET 6 和 .NET 7 中 LINQ 的 DistinctBy 方法,從而在項(xiàng)目中發(fā)揮更大的作用。
到此這篇關(guān)于.NET 中快速實(shí)現(xiàn) List 集合去重的文章就介紹到這了,更多相關(guān).net list集合去重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.net 通過(guò)URL推送POST數(shù)據(jù)具體實(shí)現(xiàn)
這篇文章主要介紹了.net 通過(guò)URL推送POST數(shù)據(jù)具體實(shí)現(xiàn),有需要的朋友可以參考一下2013-12-12
使用Aspose.Cells實(shí)現(xiàn)導(dǎo)入導(dǎo)出
這篇文章主要為大家詳細(xì)介紹了如何使用Aspose.Cells實(shí)現(xiàn)導(dǎo)入導(dǎo)出,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Visual Studio中調(diào)試 .NET源代碼的實(shí)現(xiàn)步驟
在調(diào)試 .NET 應(yīng)用程序時(shí),有時(shí)你可能需要查看其他人的源代碼,本文主要介紹了Visual Studio中調(diào)試 .NET源代碼的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
注冊(cè)表中存儲(chǔ)數(shù)據(jù)庫(kù)鏈接字符串的方法
2008-01-01
深入理解Asp.net中DataBinder.Eval的用法總結(jié)
本篇文章是對(duì)Asp.net中DataBinder.Eval的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
.net core項(xiàng)目中自定義服務(wù)的實(shí)現(xiàn)步驟
本文詳解.NET?Core自定義服務(wù)實(shí)現(xiàn),涵蓋接口定義、類實(shí)現(xiàn)、注冊(cè)(Transient/Scoped/Singleton)、注入使用及高級(jí)方法(工廠/多實(shí)現(xiàn)),通過(guò)緩存服務(wù)案例展示實(shí)際應(yīng)用,強(qiáng)調(diào)松耦合設(shè)計(jì)與生命周期管理對(duì)代碼可維護(hù)性的重要性,感興趣的朋友一起看看吧2025-07-07
開(kāi)源跨平臺(tái)運(yùn)行服務(wù)插件TaskCore.MainForm
這篇文章主要為大家詳細(xì)介紹了開(kāi)源跨平臺(tái)運(yùn)行服務(wù)插件TaskCore.MainForm的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06

