[英]C# distinct List<string> by substring
我想從字符串列表中刪除重復項。 我通過使用distinct來做到這一點,但我想在比較時忽略第一個char。
我已經有一個刪除重復項的工作代碼,但我的代碼也刪除了每個字符串的第一個字符。
List<string> mylist = new List<string>();
List<string> newlist =
mylist.Select(e => e.Substring(1, e.Length - 1)).Distinct().ToList();
輸入: “1A” ,“1B”, “2A” ,“3C”,“4D”
輸出:“A”,“B”,“C”,“D”
右輸出:“1A”,“2B”,“3C”,“4D”如果刪除“1A”或“2A”則無關緊要
我想我非常接近......但任何輸入都非常感謝!
一如既往,解決方案應盡可能快地工作;)
您可以實現IEqualityComparer<string>
,它將通過忽略第一個字母來比較您的字符串。 然后將其傳遞給Distinct
方法。
myList.Distinct(new MyComparer());
MSDN上還有一個示例,向您展示如何使用Distinct
實現和使用自定義比較器。
除了第一個字符外,您可以使用GroupBy
並獲取每個組中的第一個字符:
List<string> result= mylist.GroupBy(s => s.Length < 2 ? s : s.Substring(1))
.Select(g => g.First())
.ToList();
結果:
Console.Write(string.Join(",", result)); // 1A,1B,3C,4D
是否刪除“1A”或“2A”無關緊要
如果你改變主意,你必須用新邏輯替換g.First()
。
但是,如果性能真的很重要,並且您希望刪除哪個副本永遠不重要,那么您應該更喜歡Selman的方法 ,該方法建議編寫自定義IEqualityComparer<string>
。 如果它的GetHashCode
實現如下,那將比我的GroupBy
方法更有效:
return (s.Length < 2 ? s : s.Substring(1)).GetHashCode();
我將建議一個簡單的擴展,您可以在類似的情況下重用
public static IEnumerable<T> DistinctBy<T, U>(this IEnumerable<T> This, Func<T, U> keySelector)
{
var set = new HashSet<U>();
foreach (var item in This)
{
if (set.Add(keySelector(item)))
yield return item;
}
}
這基本上是在Linq中實現Distinct的方式。
用法:
List<string> newlist =
mylist.DistinctBy(e => e.Substring(1, e.Length - 1)).ToList();
我意識到已經給出了答案,但是因為我正在研究這個答案,所以我仍然會發布它,以防它有用。
如果您真的想要大型列表的最快解決方案,那么這樣的事情可能是最佳的。 但是,您需要做一些准確的計時才能確定!
在比較或計算哈希碼時,此方法不會生成任何其他字符串副本:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
internal static class Program
{
static void Main()
{
var myList = new List<string>
{
"1A",
"1B",
"2A",
"3C",
"4D"
};
var newList = myList.Distinct(new MyComparer());
Console.WriteLine(string.Join("\n", newList));
}
sealed class MyComparer: IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
if (x.Length != y.Length)
return false;
if (x.Length == 0)
return true;
return (string.Compare(x, 1, y, 1, x.Length) == 0);
}
public int GetHashCode(string s)
{
if (s.Length <= 1)
return 0;
int result = 17;
unchecked
{
bool first = true;
foreach (char c in s)
{
if (first)
first = false;
else
result = result*23 + c;
}
}
return result;
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.