【问题标题】:logically sorting a mixed string of uppercase letters and numbers对大写字母和数字的混合字符串进行逻辑排序
【发布时间】:2013-10-07 16:52:45
【问题描述】:

我有一串大写字母和数字,我必须对它们进行“逻辑”排序并存储在数据库的某个字段中。我已经弄清楚了数据库中的更新/更改/查询部分。我很难对这个字符串进行逻辑排序。

到此为止,希望我能解释清楚。

给定这组字符串 AB1 AB2 AB3 A11 AB10

我需要像这样进行 alpha 排序

A11 AB1 AB2 AB3 AB10

为了实现这一点,我相信我需要爆炸字符串。因为目前尝试 alpha 排序会产生 A11 AB1 AB10 AB2 AB3

编辑:我需要能够存储一个展开的字符串和一个非展开的字符串,以便能够与其他程序进行排序。

这是我认为需要将它们分解和存储以便对 alpha 进行排序的方式

A11  -  A   11
AB1  -  AB   1
AB2  -  AB   2
AB3  -  AB   3
AB10 -  AB  10

有一些常数。该字符串将不超过 5 个位置。它只会包含大写字母和数字。

这是我的代码。作家们阻止了,所以我希望能得到一些帮助。我想我需要找到它是否以字母开头,然后找到所有连续的字母,将那些向左移动,然后去处理数字,找到所有连续的数字并将那些向右对齐。不知道像“A1B1”这样的东西会如何工作......

for(int ii = 0;ii < sectionString.length() && ii< SECTIONSPACES;ii++){
               System.out.print("    Was previous a number? " + isPreviousANumber +         "\n");
try{
    String tmpString = sectionString.substring(ii,ii + 1 );
    int positionInCharArray = Integer.parseInt(tmpString);
    System.out.printf("    Position " + ii + " is number " + positionInCharArray + "\n");
    isPreviousANumber = true;        
}catch(Exception e){
    System.out.printf("    Position " + ii + " number is not a number " +      sectionString.substring(ii,ii) + "\n");
    isPreviousANumber = false;
    }                   
}

【问题讨论】:

  • 采用类似于基数排序的方法,数字优先于字母。
  • 我将复制我在下面所做的评论 如果我可以使用 java 对它们进行排序,这些对它们进行排序非常有用。问题是不同的程序需要对它们进行排序并与它们兼容,我需要“分解”字符串并使用分解后的字符串进行排序并仅显示常规值。不“正常”,我知道。在 db 中会有两个字段,一个称为 section,一个称为 sort_section。有意义吗?

标签: java algorithm sorting


【解决方案1】:

这句话“不确定像 'A1B1' 这样的东西是如何工作的......”在某种程度上增加了问题的复杂性。以下应该适用于所有情况。

方法:

将字符串分成标记。记号可以是一个字母,也可以是一串连续的数字。用前导空格将每个数字标记填充到五个字符。连接标记以形成爆炸字符串。

从 5 个字符的原件中,最长的分解字符串将是 17 个字符。

生成的分解字符串可以按任何程序排序,也可以按 SQL“ORDERED BY”子句排序。

例子:

1A1A1   "    1A    1A    1"
11A11   "   11A   11"
1111A   " 1111A"
11111   "11111"
A1      "A    1"
A1B1    "A    1B    1"
A1C     "A    1C"
A2      "A    2"
A2B1    "A    2B    1"
A10     "A   10"
A10B1   "A   10B    1"
A11     "A   11"
AA1     "AA    1"
AB1     "AB    1"
AB2     "AB    2"
AB10    "AB   10"
ABC     "ABC"

伪代码:

// original = "section" string
exploded = ""
prevdigits = false
for ii from 1 to length(original) {
   ch = original[ii]
   if (ch is a digit) then {
      if not prevdigits then {
         token = ""
         prevdigits = true
      }
      token = token+ch
   } else { // letter
      if prevdigits then {
         exploded = exploded + spaces(5-length(token)) + token
         prevdigits = false
      }
      exploded = exploded + ch
   }
}

-阿尔。

【讨论】:

  • 我不喜欢添加最后一句话。我只是想出了同样的事情,然后回来更新我的代码。
【解决方案2】:

这是我使用基数排序想法对其进行排序的方法:

public static String[] radixSort(String[] strings){
    // Pad the strings
    for(int i=0; i<strings.length; i++){
        strings[i] = String.format("%-5s", strings[i]);
    }

    // Radix sort them
    for (int digit = 0; digit < 5; digit++) {
        final int i = digit;
        Arrays.sort(strings, new Comparator<String>() {


            @Override
            public int compare(String o1, String o2) {
                return o1.charAt(i) - o2.charAt(i);
            }
        });
    }

    // Then trim the whitespaces we used to pad

    for (int i = 0; i < strings.length; i++) {
        strings[i] = strings[i].trim();
    }

    return strings;
}

有输入

    String[] strings = new String[] { "AB1", "AB2", "AB3", "A11", "AB10" };
    System.out.println(Arrays.toString(radixSort(strings)));

然后输出

[A11, AB1, AB2, AB3, AB10]

我不确定这是最有效的方法,但它可以完成工作。

【讨论】:

  • 如果我可以使用 java 对它们进行排序,这些对它们进行排序非常有用。问题是不同的程序需要对它们进行排序并与它们兼容,我需要“分解”它们并使用分解后的字符串进行排序并仅显示常规值。不“正常”,我知道。在 db 中会有两个字段,一个称为 section,一个称为 sort_section。有意义吗?
  • 不知道第二个要求,将它们包装在另一个对象中,如 marco 建议的那样,添加 getter 或使用正则表达式将我排序的字符串拆分为 alpha 和数字值。
  • 那是我的错,我在原帖中添加了这个要求
  • Np :) 当我发布问题时,我也倾向于忘记。有时我什至在设计迫使我完全重写之后很久还记得一个约束。
【解决方案3】:

您可以使用另一个类作为字符串的特殊表示。像这样:

public class AlphaNumericString implements Comparable<AlphaNumericString> {
    public final String alphaPart;
    public final Long numericPart;

    public AlphaNumericString(String string) {
        int index = 0;
        while (index < string.length() && !Character.isDigit(string.charAt(index))) {
            index++;
        }

        alphaPart = string.substring(0, index);

        if (index < string.length()) {
            numericPart = new Long(string.substring(index));
        } else {
            numericPart = null;
        }
    }

    @Override
    public int compareTo(AlphaNumericString other) {
        int stringCompareResult = alphaPart != null ? alphaPart.compareTo(other.alphaPart) : -1;

        if (stringCompareResult == 0) {
            return numericPart != null ? numericPart.compareTo(other.numericPart) : -1;
        } else {
            return stringCompareResult;
        }
    }

    @Override
    public String toString() {
        return (alphaPart != null ? alphaPart : "") + (numericPart != null ? numericPart : "");
    }
}

您可以将当前的字符串转换为此类,根据需要对其进行排序和转换

【讨论】:

    【解决方案4】:

    我会用空格将这些字符串补全为 5 个符号,然后生成 Radix Sort 。我们可以将所有符号作为字符进行比较。

        String[] array = {"A11", "AB1", "AB2", "AB3", "AB10"};
    
        int i, j, length;
        for (i = 0; i < array.length; i++) {
            length = array[i].length();
            for (j = length; j < 5; j++) {
                array[i] += " ";
            }
        }
    
        Arrays.sort(array);
    
        for (int k = 0; k<array.length; k++)
            System.out.println(array[k]);
    

    【讨论】:

      【解决方案5】:

      这是我的代码。我确信它可以简化,这是我有一个大脑孩子需要写作的那些停电时刻之一。如果数字字符串长度超过 5 个字符,这将不起作用...

      更新:不那么丑了

      private String buildPieceSortNumber(String pieceNumber){
          final int INTSPACES = 5;
          final String SPACE = " ";
          String explodedSection = "";        
          char[] charArray = pieceNumber.toCharArray();
          String ints = "";
          for(int i = 0;i < charArray.length;i++){
              if(Character.isDigit(charArray[i])){
                  //add to the int string
                  ints += charArray[i];
                  //check if the next character in the array is a number
                  int nextChar = i + 1;
                  //make sure we don't go past the end of the string                
                  if(nextChar < charArray.length){
                      if(!Character.isDigit(charArray[nextChar])){
                          //end of numbers, take ints string, and add padding up to five positions
                          while(ints.length() < INTSPACES){
                              ints = SPACE + ints;
                          }
                          //add the int string to the end of the exploded string
                          explodedSection += ints;                        
                          //clear the int string 
                          ints = "";
                          }
                  }else{
                      //end of numbers, take ints string, and add padding up to five positions
                      while(ints.length() < INTSPACES){
                          ints = SPACE + ints;
                      }
                      //add the int string to the end of the exploded string
                      explodedSection += ints;
                      //clear the int string 
                      ints = "";
                  }                
              }else{
                  explodedSection += charArray[i];                                                            
              }
          }
          return explodedSection;
      

      【讨论】:

        【解决方案6】:

        您真的需要在将数据放入数据库之前对其进行排序吗?考虑让数据库为您完成工作。

        假设您将值直接写入数据库。你的数据库可能允许你做一些像我一样的事情。在 DB2 中,为了只获取字母,我会将所有数字转换为空格,然后删除所有空格。同样的概念也适用于只获取数字。

        SELECT replace(translate(inp, @spaces, @digits),' ','') as alpha, 
               int(replace(translate(inp, @spaces, @letters),' ','')) as nbr,
               ....
        

        虽然这可能是一种标准化的数据库方法,但您可能会质疑每次从表中检索数据时执行此计算。因此,在将数据写入表时执行此操作

        INSERT INTO yourtable ( item, alpha, nbr, ..... )
             VALUES (inp,
                     replace(translate(inp, @spaces, @digits),' ',''),
                     int(replace(translate(inp, @spaces, @letters),' ','')),
                     .....
                    )
        

        在我看来,这是更简单的逻辑,更少的代码,更容易测试/调试,有助于降低缺陷风险,并且更易于维护。当然,您的里程可能会因您的数据库而异。但这种方法似乎值得考虑。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-30
          • 1970-01-01
          • 1970-01-01
          • 2019-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-12
          相关资源
          最近更新 更多