Как отсортировать массив буквенно-цифровых строк, используя java 7 [duplicate]

Вот решение с jQuery, которое работает как шарм. Он проверяет, больше ли высота окна больше высоты тела. Если это так, то он меняет верхний край нижнего колонтитула для компенсации. Тестирование в Firefox, Chrome, Safari и Opera.

  $ (function () {var height_diff = $ (window) .height () - $ ('body') .height (); if  (height_diff & gt; 0) {$ ('#footer') .css ('margin-top', height_diff);}});   

Если ваш нижний колонтитул уже имеет верхний край (например, 50 пикселей), вам нужно будет изменить последнюю часть для:

  css (  'margin-top', height_diff + 50)  
5
задан Murtaza Khursheed Hussain 27 November 2014 в 12:58
поделиться

8 ответов

Ниже приведен отдельный пример того, как это сделать (не особо оптимизировано):

final Pattern p = Pattern.compile("^\\d+");
String[] examples = { 
   "1some", "2some", "20some", "21some", "3some", "some", "1abc", "abc"
};
Comparator<String> c = new Comparator<String>() {
    @Override
    public int compare(String object1, String object2) {
        Matcher m = p.matcher(object1);
        Integer number1 = null;
        if (!m.find()) {
            return object1.compareTo(object2);
        }
        else {
            Integer number2 = null;
            number1 = Integer.parseInt(m.group());
            m = p.matcher(object2);
            if (!m.find()) {
                return object1.compareTo(object2);
            }
            else {
                number2 = Integer.parseInt(m.group());
                int comparison = number1.compareTo(number2);
                if (comparison != 0) {
                    return comparison;
                }
                else {
                    return object1.compareTo(object2);
                }
            }
        }
    }
};
List<String> examplesList = new ArrayList<String>(Arrays.asList(examples));
Collections.sort(examplesList, c);
System.out.println(examplesList);

Выход

[1abc, 1some, 2some, 3some, 20some, 21some, abc, some]

Объяснение

  • В примере используется константа Pattern для определения того, находится ли число в исходной позиции String.
  • Если в первом String не присутствует, оно сравнивает его с второй.
  • Если он присутствует в первом, он проверяет второй.
  • Если во второй не присутствует, он сравнивает два String s как есть, снова
  • Если он присутствует в обоих, он сравнивает Integer s вместо целого String s, следовательно, приводит к численному сравнению, а не лексикографическому
  • . Если число сравнения одинаково, он возвращается к лексикографическому сравнению всего String s (спасибо MihaiC для определения этого)
6
ответ дан Community 17 August 2018 в 13:27
поделиться
  • 1
    хорошее решение, но оно сортируется по номерам сначала, затем по тексту. так что, если исходный массив имеет такой контент, как «1 some», «2some», «20some», «some some some», «some some», «some», , & Quot; аЬс & Quot ;. Он положил бы abc в конце – MihaiC 27 November 2014 в 12:30
  • 2
    @MihaiC просто вычислил вашу точку зрения. Фактически он будет помещать "abc ". перед "some". Хотя оба в конце, так как в лексикографическом сравнении приоритеты цифр над алфавитными символами. – Mena 27 November 2014 в 12:33
  • 3
    @MihaiC исправлено! См. Мое редактирование. – Mena 27 November 2014 в 12:54
  • 4
    Для меня это сработало с помощью myList.sort (c); Вместо Collections.sort (examplesList, c); Но спасибо! – Kikadass 10 May 2017 в 10:05
  • 5
    @Kikadass List.sort доступен только с Java 8, тогда как мой ответ был адаптирован для предыдущих версий Java. Если вы используете Java 8, вы можете также использовать lambdas, ссылки на методы и т. Д. Для этого случая. – Mena 10 May 2017 в 10:08

Это рабочее решение Java. Если у вас есть какие-либо предложения по коду, сообщите мне о моем Gist .

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class FB {

    public static int comparator(String s1, String s2) {

        String[] pt1 = s1.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
        String[] pt2 = s2.split("((?<=[a-z])(?=[0-9]))|((?<=[0-9])(?=[a-z]))"); 
//pt1 and pt2 arrays will have the string split in alphabets and numbers

        int i=0;
        if(Arrays.equals(pt1, pt2))
            return 0;
        else{
            for(i=0;i<Math.min(pt1.length, pt2.length);i++)
                if(!pt1[i].equals(pt2[i])) {
                    if(!isNumber(pt1[i],pt2[i])) {
                        if(pt1[i].compareTo(pt2[i])>0)
                            return 1;
                        else
                            return -1;
                    }
                    else {
                        int nu1 = Integer.parseInt(pt1[i]);
                        int nu2 = Integer.parseInt(pt2[i]);
                        if(nu1>nu2)
                            return 1;
                        else
                            return -1;
                    }
                }
        }

        if(pt1.length>i)
            return 1;
        else
            return -1;
    }

    private static Boolean isNumber(String n1, String n2) {
        // TODO Auto-generated method stub
        try {
            int nu1 = Integer.parseInt(n1);
            int nu2 = Integer.parseInt(n2);
            return true;
        }
        catch(Exception x) {
            return false;
        }

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String[] examples = {"1some", "2some", "20some", "21some", "3some", "some", "1abc", "abc"};
        List<String> values = new ArrayList<String>(Arrays.asList(examples));

        System.out.println(values);
        Comparator<String> com = (o1,o2) -> {return comparator(o1,o2);}; //lambda expression

        Collections.sort(values,com);
        System.out.println(values);
    }
}

Вывод:

[1some, 2some, 20some, 21some, 3some, some, 1abc, abc]
[1abc, 1some, 2some, 3some, 20some, 21some, abc, some]
0
ответ дан Akshay M 17 August 2018 в 13:27
поделиться

Вы можете сделать это ядро ​​в одной строке, используя регулярное выражение для извлечения числовой части:

Collections.sort(selectedNodes, new Comparator<DefaultMutableTreeNode>() {
    @Override
    public int compare(DefaultMutableTreeNode o1,
        DefaultMutableTreeNode o2) {
        return Integer.parseInt(o1.getUserObject().toString().replaceAll("\\D", "")) -
            Integer.parseInt(o2.getUserObject().toString().replaceAll("\\D", ""));
    }
});
0
ответ дан Bohemian 17 August 2018 в 13:27
поделиться
  • 1
    В вашем коде есть опечатка. Он должен быть Integer.parseInt (... Кроме того, здесь здесь требуется, чтобы строка всегда имела номер в ней. Иногда она может иметь только буквы, и это приведет к исключению. – user1567291 13 March 2018 в 23:06

Сначала сделайте буквенно-цифровой компаратор, разделяющий строку в строковых или целых частях.

public class AlphaNumericalComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        List<Object> parts1 = partsOf(o1);
        List<Object> parts2 = partsOf(o2);
        while (!parts1.isEmpty() && !parts2.isEmpty()) {
            Object part1 = parts1.remove(0);
            Object part2 = parts2.remove(0);
            int cmp = 0;
            if (part1 instanceof Integer && part2 instanceof Integer) {
                cmp = Integer.compare((Integer)part1, (Integer)part2);
            } else if (part1 instanceof String && part2 instanceof String) {
                cmp = ((String) part1).compareTo((String) part2);
            } else {
                cmp = part1 instanceof String ? 1 : -1; // XXXa > XXX1
            }
            if (cmp != 0) {
                return cmp;
            }
        }
        if (parts1.isEmpty() && parts2.isEmpty()) {
            return 0;
        }
        return parts1.isEmpty() ? -1 : 1;
    }

    private List<Object> partsOf(String s) {
        List<Object> parts = new LinkedList<>();
        int pos0 = 0;
        int pos = 0;
        boolean wasDigit = false;
        while (true) {
            if (pos >= s.length()
                    || Character.isDigit(s.charAt(pos)) != wasDigit) {
                if (pos > pos0) {
                    String part = s.substring(pos0, pos);
                    parts.add(wasDigit? Integer.valueOf(part) : part);
                    pos0 = pos;
                }
                if (pos >= s.length()) {
                    break;
                }
                wasDigit = !wasDigit;
            }
            ++pos;
        }
        return parts;
    }
};

Затем используйте этот компаратор в своем собственном, на Java 8 вы можете просто использовать статические методы компаратора.

2
ответ дан Joop Eggen 17 August 2018 в 13:27
поделиться
  • 1
    @Eggen Спасибо, человек сделал работу решетки! – Rajesh Hatwar 27 April 2018 в 12:31

Ваше решение лежит в Алфавитный алгоритм , и вы можете реализовать как этот

3
ответ дан Murtaza Khursheed Hussain 17 August 2018 в 13:27
поделиться

Вы не можете использовать стандартную String compareTo (), вместо этого нужно сравнить строки, следуя приведенному ниже алгоритму.

  1. Прокрутите первый и второй строковый символ по символу и получите кусок всего строки или числа
  2. Проверьте, являются ли куски числами или строками
  3. Если числа сортируются численно, используйте String compareTo ()

Повторите шаги.

0
ответ дан Roshith 17 August 2018 в 13:27
поделиться
    String [] str = new String[]{"1some", "2some", "20some", "21some", "3some", "some"};
    List<String> list = Arrays.asList(str);

    Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
    System.out.println(list);
-4
ответ дан Vishu 17 August 2018 в 13:27
поделиться
  • 1
    Это не делает то, что задает вопрос. См. ideone.com/mWhPIT . Вопрос задает порядок 1some, 2some, 3some, 20some, 21some, some. – Radiodef 13 July 2018 в 14:49

Для выполнения этой пользовательской сортировки вам необходимо реализовать свой собственный Comparator. По умолчанию метод String.compareTo() сортирует числа перед символами. Когда 0 в 20some сравнивается с s в 3some, 0 имеет более высокий приоритет сортировки, и поэтому все слово сортируется первым. Что вам нужно сделать, так это: попытайтесь разделить строки на число и часть символа. Это сложная задача, поскольку эти String s могут состоять из многих из этих частей (или не так?). Вы можете использовать такие алгоритмы, как Alphanum, которые Муртаза уже показал вам. Если вы хотите реализовать его самостоятельно, вы можете проверить, заканчивается ли числовая часть. Затем проанализируйте его с int с помощью Integer.parse(). Сравните int части, если они существуют в обоих String s, а затем сравните остальные. Ну, это может быть не самое профессиональное решение, но, как новичок, вы можете попробовать эти вещи сами изучить.

0
ответ дан Zhedar 17 August 2018 в 13:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: