Вопрос:

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

java sorting

40299 просмотра

6 ответа

1633 Репутация автора

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

room1, room2, room100

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

room1, room100, room2

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

Автор: MAGx2 Источник Размещён: 20.12.2012 01:43

Ответы (6)


0 плюса

15400 Репутация автора

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

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

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

6 плюса

10979 Репутация автора

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

    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 плюса

167 Репутация автора

Вот моя 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

41 плюса

317180 Репутация автора

Решение

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

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

0 плюса

6070 Репутация автора

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

Автор: SkyWalker Размещён: 20.12.2012 01:56

8 плюса

832 Репутация автора

Использовал @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
Вопросы из категории :
32x32