java - 如何计算数组中的整数组,而不对数组进行排序?
问题描述
我的目标是能够计算数组中相同整数的组。例如,在这样的数组中{1, 1, 1, 2, 2, 3, 1, 1}
,有4 个组:
- 至少大小 1:3 组
- 至少大小为 2:1 组
- 至少大小 3
我在没有对数组进行排序的情况下完成此操作时遇到问题。当它被排序时,我失去了数组末尾的两个 1 组的计数,因为它被放在其他 1 组旁边。
int result = (int) Stream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
.collect(Collectors.groupingBy(i -> i))
.entrySet().stream()
.filter(entry -> entry.getValue().size() >= 1) // specify the size
.count()
return result;
每种尺寸的预期输出如下:
size 1 count == 8
size 2 count == 5
size 6 count == 1
size 8 count == 1
实际输出如下:
size 1 count == 6
size 2 count == 3
size 6 count == 2
size 8 count == 1
差异是数组在计数发生之前排序的结果。有没有办法做到这一点?
编辑: 一个组基本上是相同整数重复的任何地方,直到一个不同值的整数在它前面;因此,此代码中大小为 2 的组是索引 0 到 2(含)、索引 4 - 5(含)、索引 6 - 15(含、索引 16 - 18(含)和索引 20 -22 处的任何组(包括在内)由于有 5 个组的大小至少为 2,因此应返回 5 个计数。
我的目标的命令式代码风格。
Scanner key = new Scanner("1 1 1 2 1 1 3 3 3 3 3 3 3 3 3 3 4 4 4 5 4 4 4 6");
int cnt = 0;
int counter = 0;
int i = 0;
while(key.hasNextInt()) {
int next = key.nextInt();
if(next == array[i]) {
counter++;
}
if(i + 1 < array.length && i -1 >= 0
&& counter >=size
&& next != array[i + 1]
&& next == array[i-size + 1]) {
cnt++;
counter = 0;
}
i++;
}
return cnt;
预期回报与上述相同。
实际回报为:
size 1 count == 7
size 2 count == 5
size 6 count == 3
size 8 count == 1
这个循环的问题是我相信它跳过了数组的第一块和最后一块。
我没有与Stream方式相同的排序问题。
理想情况下,这不需要任何外部实用程序/库。
解决方案
首先,我建议找到所有子组。为此,您可以使用Stream.collect()
自定义收集器:
List<List<Integer>> sublists = IntStream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
.collect(ArrayList::new, (lists, value) -> {
if (lists.isEmpty() || lists.get(lists.size() - 1).stream().noneMatch(e -> e == value)) {
lists.add(new ArrayList<>());
}
lists.get(lists.size() - 1).add(value);
}, (l1, l2) -> {
throw new RuntimeException("not supported for parallel streams");
});
结果是:
[[1, 1, 1], [2], [1, 1], [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 4, 4], [5], [4, 4, 4], [6]]
现在您可以使用它对列表大小进行分组:
Map<Integer, Long> result = sublists.stream()
.collect(Collectors.groupingBy(List::size, Collectors.counting()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
这会找到所有现有的组大小和打印:
size 1 count 3
size 2 count 1
size 3 count 3
size 10 count 1
要计算具有最小长度的所有组,您可以使用:
Map<Integer, Long> result = IntStream.rangeClosed(1, sublists.stream().mapToInt(List::size).max().orElse(0)).boxed()
.collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
这打印:
size 1 count 8
size 2 count 5
size 3 count 4
size 4 count 1
size 5 count 1
size 6 count 1
size 7 count 1
size 8 count 1
size 9 count 1
size 10 count 1
要仅获得一组预定义的尺寸(例如1, 2, 6, 8
),您可以修改最后一个解决方案:
Map<Integer, Long> result = IntStream.of(1, 2, 6, 8).boxed()
.collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
结果是:
size 1 count 8
size 2 count 5
size 6 count 1
size 8 count 1
推荐阅读
- javascript - 使用 Postman 工具向 Yammer API 发出 Get 请求,但不适用于 Vue-Resource
- python - 'pygame.error: 视频系统未初始化'
- angular - Ag-Grid 断言错误:传入的类型不是 ComponentType,它没有“ɵcmp”属性
- mysql - 查询 sys.x$session 很慢
- java - TimePickerDialog 构造函数问题
- google-apps-script - 超链接单击后复制单元格的文本到另一个单元格
- python - Python 键盘输入
- ios - iOS App 使用错误的默认语言作为应用名称
- c# - SQL Server:执行存储过程问题
- c# - 如何将 .net core Web API 项目添加到现有的 .NET core (3.1) Web Application 项目中?