получите цифры, которые являются частью строки, а затем выполните сортировку строк

#java

Вопрос:

Допустим, у вас есть массив, содержащий строки:

 arr1={"sell 1, time 4, item 4", "buy 3, time 2, item 5"}  

вы хотите отсортировать элементы по «времени» в порядке возрастания, как это можно сделать? Так что вы бы:

 arr1={"buy 3, time 2, item 5", "sell 1, time 4, item 4"}  

Может быть, объединить каждую строку и повторять каждый символ, пока не встретите цифру?

Я попытался сделать следующее:

 String[] arr1={"sell 1, time 4, item 4", "buy 3, time 2, item 5"};  String singleString = arr1[0];  int indexOfNumber=singleString.indexOf("time") 5;    System.out.println(singleString.charAt(indexOfNumber));  

Я как-то думаю о цикле for, но не могу придумать, как это сделать.

Комментарии:

1. Разбейте это на более мелкие кусочки. Например, на одном шаге напишем метод, который разберет строку на более значимые фрагменты данных. Затем, после того как у вас будет этот метод, вы сможете применить его к каждой строке в массиве. Затем, наконец, вы можете отсортировать массив.

Ответ №1:

Вы можете использовать API потоков Java.

1. Смоделируйте вещь, с которой вы работаете

Ваша строка, разделенная запятыми, представляет что-то. Что это? Я назвал его ан Event , со свойствами

  • действие, либо покупайте, либо продавайте;
  • количество, число, стоящее за действием;
  • время, число, стоящее за текстом «время»; и
  • товар, номер за текстом «товар».

Теперь вы можете создать модель только с помощью этого:

 record Event(String action, int quantity, int time, int item) { }  

Примечание: записи доступны с Java 16. Если вы используете более низкую версию Java, то вместо этого вам нужно создать класс. Убедитесь, что вы создали конструктор, принимающий и устанавливающий все поля, и убедитесь, что вы создали геттеры. Обратите внимание, что для записей компилятор автоматически создает методы доступа с тем же именем, что и для полей.

2. Создайте метод, способный анализировать строку в Event

Например, ваша входная строка, по "sell 1, time 4, item 4" -видимому, имеет фиксированную структуру. Что происходит в приведенном ниже фрагменте кода, так это то, что я предполагаю, что здесь всегда так. Если мы разделимся либо пробелом, либо запятой, за которой следует пробел, то у нас будет шесть элементов (с индексами 0 — 5). Каждый из этих шести элементов содержит часть информации, соответствующую нашей модели:

 Event parseEvent(String input) {  String[] parts = input.split(",? ");  String action = parts[0];  int quantity = Integer.parseInt(parts[1]);  int time = Integer.parseInt(parts[3]);  int item = Integer.parseInt(parts[5]);  return new Event(action, quantity, time, item); }  

3. Проведите поток по элементам, преобразуя эти строки, разделенные запятыми, в красивые Event модели, а затем отсортируйте по time свойству вашей модели:

 Stream.of(arr1)  .map(element -gt; parseItem(element)) // Convert string to Event instance  .sorted(Comparator.comparing(Event::time))  .forEach(System.out::println);  

Комментарии:

1. FWIW, вы можете использовать ссылку на метод this::parseItem вместо лямбды. Не держи меня за это, но я думаю, что конвенция о кодировании предпочитает первое второму.

Ответ №2:

вы можете использовать регулярное выражение, чтобы получить число, следующее даст вам число в виде строки "time (d)" , которую вы затем можете отсортировать

Ответ №3:

Если имена строк имеют постоянную длину (они указаны в вашем примере), то вы можете просто подсчитать количество символов и использовать значение времени для сортировки. Например, первое значение времени начинается с индекса 14. Если имена не имеют постоянной длины, вы можете использовать регулярное выражение для извлечения значения времени из каждой строки. Кроме того, вы также можете разделить каждую строку разделителем , , а затем снова разделить 2-й элемент пробелом и выбрать последний элемент.

Ответ №4:

Для сортировки массива используйте Arrays.sort с помощью a Comparator . В вашем случае сравнение выполняется в поле, которое вы найдете с регулярным выражением.

Так:

 Pattern timePattern = Pattern.compile("time (\d )"); Functionlt;String,Integergt; getTime = s -gt; {  Matcher matcher = timePattern.matcher(s);  return matcher.find() ? Integer.parseInt(matcher.group(1)) : 0; }; Comparatorlt;Stringgt; sortByTime = Comparator.comparingInt(getTime);  

Затем вы можете отсортировать массив следующим образом:

 Arrays.sort(array, sortByTime);  

Ответ №5:

Я бы сделал это следующим образом.

 String[] arr1 = { "sell 2, time 3", "sell 1, time 4, item 4",  "buy 3, time 2, item 5", "sell 6, time 1, item 8" };  
  • во-первых, используйте AbstractMap.SimpleEntry * для хранения строки и критериев сортировки.
  • затем выполните сортировку по value части записи.
  • извлеките key часть
  • и возвращайтесь в виде массива.
 arr1 = Arrays.stream(arr1).map(  str -gt; new AbstractMap.SimpleEntrylt;String, Integergt;(  str, extract(str)))  .sorted(Entry.comparingByValue(Integer::compare))  .map(Entry::getKey).toArray(String[]::new);  for (String s : arr1) {  System.out.println(s); }  

С принтами

 sell 6, time 1, item 8 sell 3, time 2, item 5 sell 2, time 3, item 9 sell 1, time 4, item 4  

Вот вспомогательный метод для извлечения time значения.

  • используйте регулярное выражение для записи определенного значения поля
  • и возвращайтесь в виде целого числа.
 public static Integer extract(String str) {  Matcher m = Pattern.compile("time\s (\d )").matcher(str);  m.find();  return Integer.valueOf(m.group(1)); }  

* Для больших списков я предпочитаю использовать Entry метод, так extract как метод вызывается только один раз для каждого значения, а не для каждого сравнения.