当前位置: 首页 > 知识库问答 >
问题:

删除值以只保留N个事件

邹麻雀
2023-03-14
{1,2,3,4,1}, N=1 -> {1,2,3,4}
{2,2,2,2}, N=2 -> {2,2}
 public static int[] deleteNth(int[] elements, int maxOcurrences) {
    List<Integer> ints = Arrays.stream(elements)
                               .boxed()
                               .collect(Collectors.toList());
    return ints.stream().filter(x -> Collections.frequency(ints, x) <= maxOcurrences)
        .mapToInt(Integer::intValue)
        .toArray();
}

PS:我知道O(n^2),但这对我来说不是问题。

共有1个答案

董弘新
2023-03-14

我认为这是一个不使用流的好例子。当涉及有状态操作时,流并不总是最好的方法。

但这是绝对可以做到的,而且这个问题还专门针对流提出,所以您可以使用以下内容。

使用forEachOrdered

public static int[] deleteNth(int[] elements, int maxOcurrs) {
    List<Integer> list = new ArrayList<>();
    Arrays.stream(elements).forEachOrdered(elem -> {
        if (Collections.frequency(list, elem) < maxOcurrs) list.add(elem);
    });
    return list.stream().mapToInt(Integer::intValue).toArray();
}

当流是有序的和连续的时,例如arrays.stream(元素).boxed()collect()方法不使用组合器操作符(对于java8和java9当前的realease,这是事实,但是不能保证在下一个版本中完全相同,因为可能会进行许多优化)。

这个实现保持了流的顺序,正如前面提到的,在当前的版本中可以很好地工作。就像下面链接中的答案所说的那样,我个人也认为,在顺序流中实现collect时需要使用组合器是非常困难的。

collect方法的代码如下:

public static int[] deleteNth(int[] elements, int maxOcurrs) {
    return Arrays.stream(elements).boxed()
            .collect(() -> new ArrayList<Integer>(),
                    (list, elem) -> {
                        if (Collections.frequency(list, elem) < maxOcurrs) list.add(elem);
                    },
                    (list1, list2) -> { 
                        throw new UnsupportedOperationException("Undefined combiner"); 
                    })
            .stream()
            .mapToInt(Integer::intValue)
            .toArray();
}

这个收集器创建一个ArrayList,并在添加新元素时检查是否满足MaxOcurrences,如果不满足,则添加该元素。正如前面提到的,在下面的回答中,合并器根本没有被调用。这比n^2好一点。

关于为什么在序列流中不调用组合器方法的更多信息可以在这里找到。

 类似资料:
  • 我正在尝试使用 Jsoup 删除 HTML 页面标记之间的所有文本 例如,如果输入HTML是 输出应该是 基本上,我想删除返回的内容。 我找到了很多相反的帖子,只保留文本,但没有解决我的问题。知道怎么做吗? 编辑 maverick9999:https://stackoverflow.com/a/24292349/3589481提出的解决方案将解决大部分情况。 然而,正如评论中提到的,这个解决方案也

  • 我使用Pandas read_csv从csv文件导入了一个数据帧。它的形状是735,36。我需要删除最后33列-保留前3列。这些列是,, 我已经尝试了这里所有的建议 无论我做什么,我都会得到以下错误: 例如: 我又开始了。“bool对象不可下标”错误已经消失,我认为df已经被覆盖。 我试图使用一些公开的医院活动数据,并从中提取数据。我是一名神经外科医生,所以你可能需要耐心。数据在这里https:/

  • 我想每天定期使用批处理文件进行备份。考虑以下文件夹: 游戏文件夹中有: 我需要一个批处理文件 验证(文件夹或其中的任何文件)上的时间戳是否早于1天,如果是,则继续,否则停止; 删除文件夹或其内容;将的文件夹/文件复制到文件夹; 删除文件夹或其内容;将的文件夹/文件复制到文件夹; 等直到文件夹。 最后将游戏文件夹复制到文件夹。 有可能吗? 我的想法是运行一个计划任务(Windows),然后。bat文

  • 我正在尝试删除图表的边框,而不删除标签刻度 我已经搜索了设置来做到这一点,但没有发现一个“显示:假”将隐藏一切。 我正在使用的图表可以在这里看到:https://codepen.io/paufar/pen/VOpZGQ

  • 问题 在迭代操作或者其他操作的时候,怎样只保留最后有限几个元素的历史记录? 解决方案 保留有限历史记录正是 collections.deque 大显身手的时候。比如,下面的代码在多行上面做简单的文本匹配, 并返回匹配所在行的最后N行: from collections import deque def search(lines, pattern, history=5): previous_

  • 假设我有一个像这样的html片段: 我想从中得到的是: 所以我的问题是:如何从html中去掉所有包装标签,只得到与html中相同顺序的文本?正如您在标题中看到的,我想使用jsoup进行解析。 重音html示例(请注意“á”字符): 我想要的是: 这个html不是静态的,一般来说,我只是想解码人类可读形式的通用html片段的每一个文本,宽度线中断。