【问题标题】:Lexicographically Sort String Array按字典顺序排序字符串数组
【发布时间】:2018-05-29 01:05:04
【问题描述】:

我一直在处理一项挑战并研究了几个小时,但仍然无法在 C# 中按字典顺序“正确”排序字符串数组或字符串列表。

我正在研究的挑战题:

  • 只考虑两个字符串的小写字母。
  • 比较它们以找出两个字符串中出现的字符。
  • 比较这些字符并找出哪个原始字符串包含每个字符的出现次数最多。
  • 将结果作为字符串附加,其格式描述哪个字符串的计数较高“1:”或“2:”,或者如果相等,则“=:”后跟该字符串中的所有字符,以“/”连接。
  • 按长度降序对结果进行排序,当长度相等时,按字典升序对子字符串进行排序。

结果的一个例子是,下面是我的输出:

"2:eeeee/2:yy/=:hh/=:rr"

“2:eeeee/2:yy/=:rr/=:hh”

另一个正确结果的例子是我的输出:

1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg

=:nnn/1:ooo/1:uuu/2:sss/=:gg/1:ii/2:aa/2:dd/2:ee

导致这种情况的代码行是:

strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray();

我尝试了不同的方法来解决这个问题,例如将字符串拆分为特定长度的单个字符串数组,执行字典顺序,然后将它们附加到结果中。但是对于许多不同的测试用例,一个会通过,另一个会失败。

我的问题是找出为什么 C# 将“=”视为 LESS THAN 数字,而实际上它在 ASCII 图表上更大。我进行了测试,这就是 String.Compare 给我的。在 Python 中,它给了我一些不同的东西。

这是我的完整代码,请随时指出任何错误。我只编程了 9 个月。我知道这不是最好的解决方案。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string s1 = "looping is fun but dangerous";
            string s2 = "less dangerous than coding";

            // Expected
            Console.WriteLine("1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg\n");

            // Result
            Console.WriteLine(StringsMix(s1, s2));
        }

        public static string StringsMix(string s1, string s2)
        {
            StringBuilder sb = new StringBuilder();
            // Convert string to char arrays order by ascending
            char[] s1Chars = s1.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();
            char[] s2Chars = s2.Where(x => char.IsLower(x)).OrderBy(x => x).ToArray();

            // Insert arrays to find characters that appear in both 
            char[] inter = s1Chars.Intersect(s2Chars).ToArray();

            for (int i = 0; i < inter.Length; i++){
                // For each character, put all occurences in their respective array
                // Get count
                char[] s1Ch = s1.Where(x => x.Equals(inter[i])).ToArray();
                char[] s2Ch = s2.Where(x => x.Equals(inter[i])).ToArray();
                int s1Count = s1Ch.Length;
                int s2Count = s2Ch.Length;

                if (s1Count > s2Count)
                {
                    string chars = new String(s1Ch);
                    sb.Append("1:" + chars + "/");
                }
                else if (s2Count > s1Count)
                {
                    string chars = new String(s2Ch);
                    sb.Append("2:" + chars + "/");
                }
                else if (s1Count == s2Count)
                {
                    string chars = new String(s1Ch);
                    sb.Append("=:" + chars + "/");
                }
            }

            string final = String.Empty;
            string[] strings = sb.ToString().Split('/');
            strings = strings.OrderByDescending(x => x.Length).ThenBy(c => c).ToArray(); // "Lexicographical ordering"

            final = String.Join("/", strings);
            strings = final.Split('/').Where(x => x.Length > 3).Select(x => x).ToArray(); // Remove trailing single characters
            final = String.Join("/", strings);
            return final;
        }
    }
}

【问题讨论】:

  • ThenBy(c =&gt; c) 应该做什么?
  • 请注意 OrderBy 接受字符串比较器作为第二个参数。如果您不提供 - 它将根据当前的文化规则进行排序。

标签: c# arrays string sorting string-comparison


【解决方案1】:

发生这种情况是因为 '=' 排序 之前 '1''2';您希望它在 个数字之后进行排序。

您可以通过在中间添加特殊条件来强制执行此顺序:

var specialOrder = "12=";
var ordered = data
    .OrderByDescending(s => s.Length)
    .ThenBy(s => specialOrder.IndexOf(s[0])) // <<== Add this
    .ThenBy(s => s);

这将确保初始字符按照specialOrder字符串中的字符顺序排序,即'1',然后是'2',然后是'='

Demo.

注意:代码假设序列没有空字符串。您的代码确保每个字符串至少包含三个字符,所以这不是问题。

【讨论】:

  • 如此接近,我收到了 IndexOutOfRangeException。
  • @HackerExecute 这意味着你有一个空字符串。
  • 我搞定了,非常感谢兄弟的帮助!
猜你喜欢
  • 1970-01-01
  • 2020-08-02
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2023-01-21
  • 1970-01-01
相关资源
最近更新 更多