Преобразовать строку в обратный массив int - PullRequest
5 голосов
/ 17 июня 2019

Я хочу оптимизировать это решение (идиоматически).

У меня есть строка, содержащая только целочисленные значения. Я хочу преобразовать эту строку в обратный массив int. Вывод должен быть целочисленным массивом

Вот мое решение:

private static int[] stringToReversedIntArray(String num) {
    int[] a = new int[num.length()];
    for (int i = 0; i < num.length(); i++) {
        a[i] = Integer.parseInt(num.substring(i, i + 1));
    }
    a = reverse(a);
    return a;
}

/*
 * Reverses an int array
 */
private static int[] reverse(int[] myArray) {
    int[] reversed = new int[myArray.length];
    for (int i = 0; i < myArray.length; i++) {
        reversed[i] = myArray[myArray.length - (i + 1)];
    }
    return reversed;
}

Input: "1256346258"
Output: {8,5,2,6,4,3,6,5,2,1}

Подскажите, пожалуйста, как сделать то же самое.

Ответы [ 8 ]

3 голосов
/ 17 июня 2019
var input = "1256346258";
var result = Arrays
        .stream(new StringBuffer(input).reverse().toString().split(""))
        .map(Integer::parseInt)
        .collect(Collectors.toList());
System.out.println(result);
2 голосов
/ 17 июня 2019

Поскольку вы извлекаете один символ за раз, использование charAt вместо substring имеет больше смысла.

И поскольку вы конвертируете один символ в int, Character.getNumericValue() имеет больше смысла, чем parseInt.

Следовательно, я бы изменил

a[i] = Integer.parseInt(num.substring(i, i + 1));

до

a[i] = Character.getNumericValue(num.charAt(i));

Вы также можете упростить обратную часть следующим образом, если не возражаете, используя Integer[] вместо int[]:

private static Integer[] stringToReversedIntArray(String num) {
    Integer[] a = new Integer[num.length()];
    for (int i = 0; i < num.length(); i++) {
        a[i] = Character.getNumericValue(num.charAt(i));
    }
    Collections.reverse(Arrays.asList(a));
    return a;
}
0 голосов
/ 17 июня 2019

Однострочник:

return IntStream
    .range(0, num.length())
    .map(i -> Character.getNumericValue(num.charAt(num.length() - i - 1)))
    .toArray();
0 голосов
/ 17 июня 2019

Вот простое решение с одним циклом for. Вы можете «перевернуть» цифры одновременно с извлечением числовых значений, просто поиграв немного с индексами:

private static int[] stringToReversedIntArray(String num) {
    int len = num.length();
    int[] a = new int[len];
    for (int i = 0; i < len; i++) {
        a[i] = Character.getNumericValue(num.charAt(len - i - 1));
    }
    return a;
}
0 голосов
/ 17 июня 2019

Решение Erans мне подходит, но мне не нравится цикл for, и я предпочитаю, если это возможно, поток API

String testString = "1256346258";
IntStream intStream = testString.chars();       
List<Integer> x = intStream.boxed().collect(Collectors.toList());
Collections.reverse(x);
int[] array = x.stream().mapToInt(i -> Character.getNumericValue(i)).toArray();
System.out.println("x: " + Arrays.toString(array));

, просто оберните его хорошим методом ...

0 голосов
/ 17 июня 2019
String str = "123456";
// Reverse String
str = new StringBuilder(str).reverse().toString();
String strArr[] = str.split("(?!^)");
// Convert to Int Array
int[] intarray = java.util.Arrays.stream(strings).mapToInt(Integer::parseInt).toArray();
0 голосов
/ 17 июня 2019

Нет необходимости повторять цикл 2 раза, вы можете использовать StringBuilder, чтобы перевернуть строку, а затем зациклить ее, чтобы сохранить результат в вашем массиве int:

  private static int[] stringToReversedIntArray(String num) {
    num = new StringBuilder(num).reverse().toString();
    int[] result = new int[num.length()]; 
    for (int i = 0; i < result.length; i++){
      result[i] = Character.getNumericValue(num.charAt(i)); 
    }
    return result;
  }

Другие варианты - просто перевернутьВаш цикл for и обратный отсчет:

for(int i = array.length - 1; i >= 0; i--){
  ...
}

Или используйте Stream API в последних версиях Java, как уже упоминалось выше в хорошем примере.

0 голосов
/ 17 июня 2019

Если вы хотите использовать потоки, вы можете сделать это примерно так:

Deque<String> deque = num.chars()
   .map(c -> Character.toString((char) c))
   .map(Integer::parseInt)
   .collect(Collector.of(
        ArrayDeque::new,
        (stack, i) -> stack.addFirst(i),
        (s1, s2) -> { s2.addAll(s1); return s2; })); //this combiner won't really be called unless the stream was parallel

Integer[] reversed = deque.toArray(new Integer[deque.size()]);

Это перебирает список только один раз.Deque может работать как стек, Last In First Out, поэтому каждый addFirst() автоматически меняет порядок, поскольку добавляет каждый элемент вперед, а не в конец списка.Вы можете затем преобразовать его в массив или использовать Deque как есть, что является нормальным Collection и реализует Iterable.

Как уже упоминалось в других ответах, вы также можете немного упростить его, например, если вы на 100% уверены, что у вас есть только цифры, потому что в упрощенной версии вы не получите NumberFormatException.

Deque<String> deque = num.chars()
   .map(c -> Character.getNumericValue((char) c))
   .collect(Collector.of(
        ArrayDeque::new,
        (stack, i) -> stack.addFirst(i),
        (s1, s2) -> { s2.addAll(s1); return s2; }));

Integer[] reversed = deque.toArray(new Integer[deque.size()]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...