【问题标题】:C# - How to sort a list of strings using last character by ignoring special character if any at the endC# - 如何通过忽略最后的特殊字符来使用最后一个字符对字符串列表进行排序
【发布时间】:2017-05-13 08:48:53
【问题描述】:

以下是我尝试实现并能够对其进行排序但需要弄清楚忽略其中的特殊字符的逻辑

我的逻辑:

  • 列表中的反转字符串
  • 升序排列
  • 再次反向排序的字符串 &
  • 最后用~分隔符作为字符串返回。

        List<String> inputLst= new List<String>() { "Bananas!", "Cherry2",
        "Mango","Apples", "Grape$", "Guava" };
    
        List<String> sortList = new List<String>();
        List<String> outputList = new List<String>();
    
        foreach (String str in inputLst)
        {
            sortList.Add(new String(str.ToCharArray().Reverse().ToArray()));
        }
        sortList.Sort();
    
        foreach (String str in sortList)
        {
            outputList.Add(new String(str.ToCharArray().Reverse().ToArray()));
        }
        Return String.Join("~", outputList);
    

我得到的输出是Bananas!~Grape$~Cherry2~Guava~Mango~Apples

预期的输出应该是Guava~Grape$~Mango~Bananas!~Apples~Cherry2

谁能建议我通过忽略特殊字符按最后一个字符对列表进行排序的优化解决方案?在这里,我使用 2 个列表进行字符串反转,可以以更有效的方式完成吗? 注意:请不要使用 LINQ。

【问题讨论】:

  • 为什么不想编写自定义比较器?

标签: c# string sorting generic-list


【解决方案1】:

通过一点 LINQ 和 Regex,这可以相对简单地实现:

var inputList = new List<string>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };

var outputList = inputList.OrderBy(s => new string(Regex.Replace(s, "[^a-zA-Z]", "")
                                                        .Reverse()
                                                        .ToArray()))
                          .ToList();

var output = String.Join("~", outputList);

编辑:非 LINQ 方法:

var inputList = new List<string>() { "Bananas!", "Cherry2", "Mango", "Apples", "Grape$", "Guava" };

inputList.Sort(new ReverseStringComparer());

var output = String.Join("~", inputList);

ReverseStringComparer:

class ReverseStringComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string a = new string(Regex.Replace(x, "[^a-zA-Z]", "").Reverse().ToArray());
        string b = new string(Regex.Replace(y, "[^a-zA-Z]", "").Reverse().ToArray());
        return a.CompareTo(b);
    }
}

【讨论】:

  • 感谢您的解决方案,它工作正常。我希望有一个不使用 LINQ 的解决方案。
【解决方案2】:

没有正则表达式的解决方案:

string foo()
{
    List<String> inputLst= new List<String>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };

    inputLst.Sort((l, r) => new string(l.Reverse().SkipWhile( x => !char.IsLetter(x) ).ToArray()).CompareTo( new string(r.Reverse().SkipWhile(x => !char.IsLetter(x)).ToArray()) ) );

    return String.Join("~", inputLst);
}

要跳过评论中建议的所有非字母字符(不仅是字符串的开头),只需使用Where 而不是SkipWhile,如下所示:

string bar()
{
    List<String> inputLst= new List<String>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };

    inputLst.Sort((l, r) => new string(l.Reverse().Where( x => char.IsLetter(x) ).ToArray()).CompareTo( new string(r.Reverse().Where(x => char.IsLetter(x)).ToArray()) ) );

    return String.Join("~", inputLst);
}

注意 WhereSkipWhile (!char.IsLetter(x)) 相比具有反转逻辑 (char.IsLetter(x))。

【讨论】:

  • 如果字符串中间有特殊字符,这将不起作用。例如,“b1a”将出现在“aaa”之前,但忽略数字,应该出现在之后。 (“aaa”与“ab”)
  • @Abion47 没什么,对于一些不想或不能使用它的人来说,这只是没有正则表达式的解决方案。它是对您的解决方案的补充,因为它使用 List 的不同机制并且已就位。问题标题也清楚地表明OP只想删除末尾的特殊字符,而不是字符串的中间或开头。
【解决方案3】:

找到最后一个符号是字母并按它排序。

var inputList = new List<string>() {
    "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };

var outputList = inputList.OrderBy(s => s.Last(c => char.IsLetter(c)));

Console.WriteLine(string.Join("~", outputList));

不需要反转。

【讨论】:

  • 同样,如果多个单词有一个共同的最后一个字符,Last() 将无法用作排序机制。
  • @Abion47 - Last(c =&gt; char.IsLetter(c)) 在单词 a&amp;b 中找到 b,而不是 a。因此,它可以正常工作。
  • "az", "dz", "cz", "bz" 列表中,元素要么保持不变,要么排序不可预测(取决于排序算法的实现),因为只考虑每个元素中的'z'
  • @Abion47 - OP 想要排序“使用最后一个字符”。所以条件满足了。
  • 他还说示例的期望输出应该是“香蕉!”在“Apples”之前,如果仅与最后一个字符进行比较,这是无法保证的。
猜你喜欢
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 2021-05-22
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
相关资源
最近更新 更多