Выполнить арифметическую операцию над строкой concat с потоками Java - PullRequest
0 голосов
/ 28 мая 2018

Привет, ребята, и спасибо всем за помощь.

У меня есть Stream<String>, где строка может быть чем-то вроде "1 + 5 * 2-4" // = 8 (все нормально, если я вычислюэто слева направо)

Эта операция не является проблемой, но я пытаюсь сделать это сейчас только с потоками. Это означает, что мне нужно использовать только потоковые операции, такие как фильтр, уменьшение, сбор ...

Я пробовал последние 6 часов и понятия не имею.Не разрешается создавать списки и анализировать элементы или что-то в этом направлении.Потоковая операция или множество потоковых операций должны дать мне конечный результат напрямую.

У кого-нибудь есть идеи?

Моя лучшая попытка была

  Stream<String> numbers = myList.stream().filter(s -> 
  Character.isDigit(s.charAt(0)));
  List<String> operands = myList.stream().filter(s -> 
  !Character.isDigit(s.charAt(0))).collect(Collectors.toList());



   String result = numbers.reduce((a, b) -> {
   int iA = Integer.parseInt(a);
   int iB = Integer.parseInt(b);

   String operation = operands.get(0);
   operands.remove(0);
   return calc(iA,iB,operation);


  }).get();

  System.out.println(result);

Обновление: я, вероятно, объяснилэто плохо.Конечный результат должен доставить потоковую операцию.В этой потоковой операции мы можем вызывать вспомогательные методы.

1 Ответ

0 голосов
/ 28 мая 2018

Рабочее решение, исправлены опечатки, благодаря @ Turing85

Java-8 Stream-API на самом деле не волшебная палочка для всего, и я не вижу простого решения с использованием лямбда-выражений.

Я предлагаю вам придерживаться процедурного пути:

String string = "1+5*2-4";

String[] operator = a.split("[0-9]+");
String[] digits = a.split("[+-\\/*]");

int reduced = Integer.parseInt(digits[0]);
for (int i = 1; i < digits.length; i++) {
    if (operator[i].equals("+")) { reduced += Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("/")) { reduced /= Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("*")) { reduced *= Integer.parseInt(digits[i]); } 
    else if (operator[i].equals("-")) { reduced -= Integer.parseInt(digits[i]); }
}

Это решение упрощено только для целых чисел и без проверки ввода и последовательности символов.Число reduced приводит к 8.Кстати, не забывайте дважды экранировать символ / с помощью \\, потому что он имеет особое значение в регулярном выражении.


Если вы действительно настаиваете на решении на основе Stream-API, которое дает тот же результат, то вы идете:

String a = "1+5*2-4";
System.out.println(a);
String[] operator = a.split("[0-9]+");
String[] digits = a.split("[+-\\/*]");

final int[] index = {0};
int reduced = Stream.of(digits)
                    .mapToInt(Integer::parseInt)
                    .reduce(0, (int t, int u) -> 
{
    int result = Integer.parseInt(digits[0]);
    int i = index[0];
    if (operator[i].equals("+")) { result = t + u; } 
    else if (operator[i].equals("/")) { result = t / u; } 
    else if (operator[i].equals("*")) { result = t * u; } 
    else if (operator[i].equals("-")) { result = t - u; } 
    index[0]++;
    return result;
}); 

Надеюсь, теперь вы можете сравнить обарезультаты, чтобы увидеть, какой из них выиграл в плане краткости и удобства обслуживания, что, на мой взгляд, важнее, чем показать, насколько вы хороши с Stream-API и лямбда-выражениями.Однако, если вы ставите перед собой задачу узнать больше о Stream-API, я предлагаю вам попытаться найти другие варианты использования.:)


РЕДАКТИРОВАТЬ: Кроме того, вы должны скрыть обработку цифр оператора для метода:

public static int process(int identity, int t, int u, String[] array, int index) {
    int result = identity;
    if (array[index].equals("+")) { result = t + u; } 
    else if (array[index].equals("/")) { result =  t / u; } 
    else if (array[index].equals("*")) { result =  t * u; } 
    else if (array[index].equals("-")) { result =  t - u; }
    return result;
}

Тогда я могу допустить, что Stream-API - не плохой выбор.

String a = "1+5*2-4";
System.out.println(a);
String operator[] = a.split("[0-9]+");
String digits[] = a.split("[+-\\/*]");

final int[] index = {0};
int reduced = Stream.of(digits).mapToInt(Integer::parseInt).reduce(0, (int t, int u) -> {
    int result = process(Integer.parseInt(digits[0]), t, u, operator, index[0]);
    index[0]++;
    return result;
}); 
...