Специфичный диапазон Java 8 Stream Api Filter - PullRequest
0 голосов
/ 21 марта 2019

У меня есть такой список:

int[] counting = new int[]{1,0,-1,-2,-1,-2,-1,0,1,2,1,0,-1,0,1,2};

Я хочу отфильтровать, если между 0 и 0 есть отрицательное значение.

Для приведенного выше списка результат должен возвращать 2, потому что между 0 и 0 есть отрицательное число, и оно также действует для третьего диапазона.

List<Integer> result = Arrays.stream(counting).filter(x ->  ).collect(Collectors.toList());

Как я могу собрать значения диапазона? После этого как я могу проверить, есть ли отрицательное число или нет?

Другими словами, я хочу посчитать, сколько пар (0, 0) существует с отрицательным значением между ними. Так как в -1, -2, -1, -2, -1 и в -1 есть отрицательное значение, количество таких пар равно 2.

Ответы [ 3 ]

3 голосов
/ 21 марта 2019

Не используйте потоковый конвейер для этого. Потоки хорошо подходят для самостоятельной обработки и фильтрации элементов. Они не подходят для обработки, которая зависит от наличия или отсутствия других элементов в потоке (здесь 0 раньше и позже).

Используйте цикл. Прежде чем войти в цикл, убедитесь, что первый элемент в списке равен 0, как требуется, и, если нет, сгенерируйте исключение (поэтому ваш список примеров из вопроса не пройдет этот тест). Объявите некоторые переменные, которые нам нужны во время цикла:

   int negativeCount = 0;
   boolean hasSeenNegativeSinceLastZero = false;

В вашем цикле, каждый раз, когда вы видите отрицательное число, установите hasSeenNegativeSinceLastZero в true. Каждый раз, когда вы видите 0, если hasSeenNegativeSinceLastZero истинно, тогда добавьте 1 к счетчику и установите hasSeenNegativeSinceLastZero в ложь.

Удачного кодирования.

1 голос
/ 21 марта 2019

Вот потоковое решение.Я сомневаюсь, что это более читабельно, чем простой цикл.

int[] zeroIndices = IntStream.range(0, counting.length)
                .filter(i -> 0 == counting[i])
                .toArray();

long count = IntStream.range(0, zeroIndices.length)
        .mapToObj(i -> new int[] { i, zeroIndices[i] })
        .skip(1)
        .filter(arr -> Arrays.stream(Arrays.copyOfRange(counting, 
                                                        zeroIndices[arr[0] - 1], 
                                                        arr[1]))
                             .anyMatch(i -> i < 0))
        .count();
0 голосов
/ 21 марта 2019

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

int[] counting = new int[] {1, 0, -1, -2, -1, -2, -1, 0, 1, 2, 1, 0, -1, 0, 1, 2};

List<Integer> indices = new ArrayList<>();
for (var i = 0; i < counting.length; i++) {
  if (counting[i] == 0) {
    indices.add(i);
  }
}

if (indices.size() % 2 == 0) {
  System.out.println("You got " + indices.size() / 2 + " pairs");
} else {
  System.err.println(
      "You don't have complete pairs, you have only " + indices.size() / 2 + " pairs");
  System.exit(-1);
}

for (var i = 0; i < indices.size(); i = i + 2) {
  System.out.println("-----Pair----");
  stream(copyOfRange(counting, indices.get(i), indices.get(i + 1)))
      .filter(v -> v < 0)
      .forEach(System.out::println);
}

Будет выводиться каждая пара, как эта

You got 2 pairs
-----Pair----
-1
-2
-1
-2
-1
-----Pair----
-1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...