我有一个这样的列表:
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的值为1,因此此类对的数量为2。
答案 0 :(得分:3)
请勿为此使用流管道。流非常适合元素的独立处理和过滤。它们不适合依赖于流中是否存在其他元素的处理(此处早晚为0)。
使用循环。在进入循环之前,请检查列表中的第一个元素是否为0(如果需要),如果不是,则抛出异常(因此问题中的示例列表将无法通过此测试)。声明我们在循环期间需要的一些变量:
int negativeCount = 0;
boolean hasSeenNegativeSinceLastZero = false;
在循环中,每次看到负数时,请将hasSeenNegativeSinceLastZero
设置为true。每次看到0时,如果hasSeenNegativeSinceLastZero
为true,则将1加到计数并将hasSeenNegativeSinceLastZero
设置为false。
快乐的编码。
答案 1 :(得分:1)
这是基于流的解决方案。我怀疑它比简单的for循环更具可读性。
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();
答案 2 :(得分:0)
我个人认为流解决方案不可读,您应该使用简单的循环,但是可以混合使用。我想这里应该是这样
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