Сортировка строк, содержащих число в Java

java sorting

40299 просмотра

6 ответа

У меня проблема с компаратором по умолчанию для строк (в SortedSet). Проблема в том, что компаратор по умолчанию не сортирует хорошую строку, содержащую числа, то есть: в наборе у меня есть:

room1, room2, room100

Естественный порядок должен быть таким же, как указано выше, но в наборе:

room1, room100, room2

Я знаю, почему это так, но я не знаю, как это изменить.

Автор: MAGx2 Источник Размещён: 13.11.2019 11:51

Ответы (6)


41 плюса

Решение

Попробуйте этот компаратор, который удаляет все нецифровые символы, а затем сравнивает оставшиеся символы как числа:

Collections.sort(strings, new Comparator<String>() {
    public int compare(String o1, String o2) {
        return extractInt(o1) - extractInt(o2);
    }

    int extractInt(String s) {
        String num = s.replaceAll("\\D", "");
        // return 0 if no digits found
        return num.isEmpty() ? 0 : Integer.parseInt(num);
    }
});

Вот тест:

public static void main(String[] args) throws IOException {
    List<String> strings = Arrays.asList("room1", "foo", "room2", "room100", "room10");
    Collections.sort(strings, new Comparator<String>() {
        public int compare(String o1, String o2) {
            return extractInt(o1) - extractInt(o2);
        }

        int extractInt(String s) {
            String num = s.replaceAll("\\D", "");
            // return 0 if no digits found
            return num.isEmpty() ? 0 : Integer.parseInt(num);
        }
    });
    System.out.println(strings);
}

Выход:

[foo, room1, room2, room10, room100]
Автор: Bohemian Размещён: 20.12.2012 01:51

8 плюса

Использовал @bohemian ответ. Просто немного улучшилось. Это сработало для меня очень хорошо ..

        Collections.sort(asdf, new Comparator<String>() {
            public int compare(String o1, String o2) {

                String o1StringPart = o1.replaceAll("\\d", "");
                String o2StringPart = o2.replaceAll("\\d", "");


                if(o1StringPart.equalsIgnoreCase(o2StringPart))
                {
                    return extractInt(o1) - extractInt(o2);
                }
                return o1.compareTo(o2);
            }

            int extractInt(String s) {
                String num = s.replaceAll("\\D", "");
                // return 0 if no digits found
                return num.isEmpty() ? 0 : Integer.parseInt(num);
            }
        });
Автор: rogoro Размещён: 13.04.2015 05:11

6 плюса

попробуй это. Я предполагал, что у вас всегда будет «комната» в начале вашей строки.

    List<String> list = Arrays.asList("room1", "room100", "room2");
    Collections.sort(list, new Comparator<String>()
    {
        @Override
        public int compare(String o1, String o2)
        {
            return new Integer(o1.replaceAll("room", ""))
                .compareTo(new Integer(o2.replaceAll("room", "")));
        }

    });
Автор: RNJ Размещён: 20.12.2012 01:47

2 плюса

Вот моя Comparatorреализация для такого рода: (строки могут начинаться с любых символов)

public class StringNumberComparator implements Comparator<String>{

    @Override
    public int compare(String o1, String o2) {
    int i1 = this.getRearInt(o1);
    int i2 = getLeadingInt(o2);
    String s1 = getTrailingString(o1);
    String s2 = getTrailingString(o2);

    if(i1==i2)
         return s1.compareTo(s2);
    if(i1>i2)
         return 1;
    else if(i1<i2)
            return -1;
    return 0;
    }

    private int getRearInt(String s) {
    s=s.trim();
    int i=Integer.MAX_VALUE;
    try {
             i = Integer.parseInt(s.split("[^0-9]+")[1]);
    } catch(ArrayIndexOutOfBoundsException e) {

    } catch(NumberFormatException f) {
            return i;
    }

    return i;
    }

    private String getTrailingString(String s) {
        return  s.replaceFirst("[0-9]", "");
    }
}
Автор: Igorry Размещён: 20.12.2012 01:47

0 плюса

Вы можете реализовать компаратор и передать его конструктору множеств. См. Http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html .

Если все ваши строки представлены в виде комнаты [число], вы можете убрать «комнату», проанализировать число и сравнить по нему.
В качестве альтернативы - вы можете хранить целые числа в наборе и печатать их с префиксом «номер».

Автор: Itay Karo Размещён: 20.12.2012 01:46

0 плюса

Ленивым вариантом было бы заставить компаратор String работать, не делая ничего лишнего (определяя свой собственный компаратор). Вы можете получить это, заполнив нулями числа внутри вашей строки следующим образом: room0001, room0002, room0100тогда будет работать компаратор строк по умолчанию. Однако вам необходимо знать максимальное значение числа, чтобы вы могли соответствующим образом адаптировать отступы.

Автор: SkyWalker Размещён: 20.12.2012 01:56
Вопросы из категории :
32x32