代码之家  ›  专栏  ›  技术社区  ›  hackerexecute

字典排序字符串数组

  •  2
  • hackerexecute  · 技术社区  · 7 年前

    我一直在研究一个挑战,并且已经研究了几个小时,但仍然无法在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#认为“=”小于数字,而实际上它在ASCII图表上更大。我运行了一个测试,这就是String。比较给我的。在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;
            }
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Sergey Kalinichenko    7 年前

    发生这种情况是因为 '=' 种类 之前 '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.

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