簡體   English   中英

C#distinct列表 <string> 通過子串

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM