5

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

说到这里,希望我能解释清楚。

给定这组字符串 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;
    }                   
}
4

6 回答 6

1

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

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]

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

于 2013-10-01T14:08:48.387 回答
1

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

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 : "");
    }
}

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

于 2013-10-01T14:18:15.170 回答
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
   }
}

-阿尔。

于 2013-10-02T07:29:28.003 回答
0

我会用空格将这些字符串补全为 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]);
于 2013-10-01T13:50:43.643 回答
0

这是我的代码。我确信它可以简化,这是我有一个大脑孩子需要写作的那些停电时刻之一。如果数字字符串的长度超过 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;
于 2013-10-02T12:25:35.610 回答
0

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

假设您将值直接写入数据库。你的数据库可能允许你做一些像我一样的事情。在 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),' ','')),
             .....
            )

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

于 2014-02-02T04:01:01.413 回答