如何在Java中对由数字和字母组成的字符串列表进行排序?

时间:2019-01-03 17:06:27

标签: java string algorithm sorting

我有一个由数字和字母组成的项目列表,如下所示:

原始列表:

Apple 1
Apple 1
Apple 4
Apple 1A
Apple 1B
Apple 1D
Apple 2A
Apple 2A
Apple 1C
Apple 1B
Apple 2C
Apple 10
Apple 11
Apple 5
Apple 11
Apple 8D
Banana 1
Banana 4
Banana 9D
Banana 9E
Banana 9C
Banana 13
Banana 16

这是来自API的搜索结果,但仅按字母ApplesBananas进行排序。现在,我想按数字(数字随机带有字母A,B,C,D,E)进行排序,如下所示:

带有A,B,C,D,E字母的数字应按数字和字母顺序进行排序。

预期列表:

Apple 1
Apple 1
Apple 1A
Apple 1B
Apple 1B
Apple 1C
Apple 1D
Apple 2
Apple 2A
Apple 2A
Apple 2C
Apple 4
Apple 5
Apple 8D
Apple 10
Apple 11
Banana 1
Banana 4
Banana 9C
Banana 9D
Banana 9E
Banana 13
Banana 16

我已经尝试过此解决方案,但是它按0-9位开头的项目来订购所有项目,如下所示:

private List<Location> sortLocationList(List<Location> locationArrayList){
  Collections.sort(locationArrayList, new Comparator<Location>(){
    @Override
    public int compare(Location o1, Location o2){
      return o1.getValue().compareToIgnoreCase(o2.getValue());
    }
  });
  return locationArrayList;
}

public class Location{

  public enum LocationType{ADDRESS, STREET, CITY}

  private JavascriptObject object;
  private LocationType locationType;
  private String value;

  public Location(LocationType locationType, String value, JavascriptObject object){
    this.locationType = locationType;
    this.value = value;
    this.object = object;
  }
}

我的解决方案返回此消息:

Apple 1
Apple 1
Apple 10
Apple 11
Apple 1A
Apple 1B
Apple 1B
Apple 1C
Apple 1D
Apple 2
Apple 2A
Apple 2A
Apple 2C
Apple 4
Apple 5
Apple 8D
Banana 1
Banana 13
Banana 16
Banana 4
Banana 9C
Banana 9D
Banana 9E

有更好的解决方案来对列表进行排序吗?

谢谢。

3 个答案:

答案 0 :(得分:4)

我认为总会有这样的模式:

"something something"

对于getValue()方法返回的所有值
并且第二个"something"将始终以带或不带尾字符的数字开头。
下面的代码将每个这样的值分为3部分,然后进行比较
第一部分按字母顺序
第二部分的数字和
3d部分按字母顺序:

private List<Location> sortLocationList(List<Location> locationArrayList){
    Collections.sort(locationArrayList, new Comparator<Location>(){
        @Override
        public int compare(Location o1, Location o2){
            String s1 = o1.getValue();
            String s2 = o2.getValue();

            if (s1.equalsIgnoreCase(s2))
                return 0;

            String[] tokens1 = s1.split(" ");
            String[] tokens2 = s2.split(" ");

            if (!tokens1[0].equalsIgnoreCase(tokens2[0]))
                return s1.compareToIgnoreCase(s2);

            int number1 = Integer.parseInt(tokens1[1].replaceAll("\\D", ""));
            int number2 = Integer.parseInt(tokens2[1].replaceAll("\\D", ""));

            if (number1 != number2)
                return number1 - number2;

            String suffix1 = tokens1[1].replaceAll("\\d", "");
            String suffix2 = tokens2[1].replaceAll("\\d", "");

            return suffix1.compareToIgnoreCase(suffix2);
        }
    });

    return locationArrayList;
}

答案 1 :(得分:1)

按字母顺序排序,字母在数字之后,'2'在'10'之后 您需要按名称,数字和后缀(可为String的字符串)排序,使用新类代替“字符串” 具有此属性(名称,数字和后缀)的

// change String to a new type
private Product value;

并解决您的问题

@Override
   public int compare(Location o1, Location o2){
      int c;
      // compare name
      c = o1.getValue().getName().compareTo(o12.getValue().getName());
      if (c == 0) {
           // if is the same name compare number
           c = o1.getValue().getNum().compareTo(o2.getValue().getNum());
               if (c ==0 && o1.getValue().getSufix() != null) {
               // if is the same number compare suffix
               c = o1.getValue().getSufix().compareTo(o2.getValue().getSufix());
           }
      }
      return c;
   }

答案 2 :(得分:0)

正如@forpas所述,将value分为3部分。

for example : "Apple 10AB"
Part1 - Apple (Alphabet)
Part2 - 10  (Digit)
Part3 - AB  (Alphabet)

Then 1. Compare Part1, if not equal do String Compare. If equals goto next step.
     2. Compare Part2(convert them to int), If not equal do int compare. If equals goto next step.
     3. Compare Part3, do String Compare.

排序代码在下面

private List<Location> sortLocationList(List<Location> locationArrayList) {
    Collections.sort(locationArrayList, new Comparator<Location>() {
        @Override
        public int compare(Location o1, Location o2) {
            String[] objArr1 = o1.getValue().split(" ");
            String[] objArr2 = o2.getValue().split(" ");

            if(objArr1[0].equalsIgnoreCase(objArr2[0])) {//if Part1 is same

                //split digits and letters separately
                String[] digLetArr1 = objArr1[1].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
                String[] digLetArr2 = objArr2[1].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
                Integer digit1 = Integer.parseInt(digLetArr1[0]);
                Integer digit2 = Integer.parseInt(digLetArr2[0]);

                //compare digit part (part2)
                if(digit1 == digit2) {

                    //Compare part3
                    if(digLetArr1.length == 1) {
                        return -1;
                    }
                    if(digLetArr2.length == 1) {
                        return 1;
                    }
                    return digLetArr1[1].compareTo(digLetArr2[1]);
                }
                else {
                    return digit1-digit2;
                }
            }
            else {
                return o1.getValue().compareToIgnoreCase(o2.getValue());
            }
        }
    });
    return locationArrayList;
}