C#distinct List <string> by substring </string>

时间:2014-08-21 08:03:20

标签: c# list distinct

我想从字符串列表中删除重复项。我通过使用distinct来做到这一点,但我想在比较时忽略第一个char。

我已经有一个删除重复项的工作代码,但我的代码也删除了每个字符串的第一个字符。

List<string> mylist = new List<string>();

List<string> newlist = 
  mylist.Select(e => e.Substring(1, e.Length - 1)).Distinct().ToList();

输入: 的&#34; 1A&#34; 下,&#34; 1B&#34;,的&#34;图2A&#34; 下,&#34;图3C&#34 ;, &#34;图4D&#34;

输出: &#34; A&#34;&#34; B&#34;&#34; C&#34;&#34; d&#34;

右输出: &#34; 1A&#34;&#34; 2B&#34;&#34;图3C&#34;&#34;图4D&#34;如果&#34; 1A&#34;并不重要。或&#34; 2A&#34;将被删除

我想我非常接近......但任何输入都非常感谢!

一如既往,解决方案应尽快发挥作用;)

4 个答案:

答案 0 :(得分:5)

您可以通过忽略第一个字母来实现IEqualityComparer<string>来比较您的字符串。然后将其传递给Distinct方法。

myList.Distinct(new MyComparer());

MSDN上还有一个示例,向您展示如何使用Distinct实现和使用自定义比较器。

答案 1 :(得分:3)

你可以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's approach来建议自定义IEqualityComparer<string>。如果GroupBy实现GetHashCode,那么这比我的return (s.Length < 2 ? s : s.Substring(1)).GetHashCode(); 方法更有效:

{{1}}

答案 2 :(得分:1)

我将建议一个简单的扩展,您可以在类似情况下重用

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();

答案 3 :(得分:0)

我意识到已经给出了答案,但是既然我正在研究这个答案,我还是会发布它,以防它有用。

如果您真的想要大型列表的最快解决方案,那么这样的事情可能是最佳的。不过,你需要做一些准确的计时!

在比较或计算哈希码时,此方法不会生成任何其他字符串副本:

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;
            }
        }
    }
}