【问题标题】:How to count occurrencies of an entity in a list with repetitions?如何计算重复列表中实体的出现次数?
【发布时间】:2018-10-13 15:15:18
【问题描述】:

我有一个 5 位数组合的列表(可能有重复:双打、三连等)。我需要计算每个组合出现在该列表中的频率。实际上,组合是一个唯一的 BitSet,其中设置了相应的位(如果组合包含数字 5,则设置第 5 位等)

给定列表

12345
34578
12345
98710
12345

我会得到

12345 -> 3
34578 -> 1
98710 -> 1

有什么可以解决这个任务的吗?就像我将 12345 字符串添加到此数据结构中三次,然后查询它以获取 12345(相应的 Bitset 对象),它返回 3 作为出现次数。我想到了 Apache Commons Frequency 类,但它没有帮助。

【问题讨论】:

  • 将列表转换为集合,然后遍历集合并计入列表
  • Map<String, Integer> counts = new HashMap<>();
  • 流可以提供帮助,请参阅stackoverflow.com/questions/23925315/…
  • 频率计数听起来像您需要的。你能解释一下it does not help吗?

标签: java algorithm data-structures


【解决方案1】:

如果您正在寻找一种即用型数据结构,它存储 元素和计数,那么 Guava's Multiset 正是这样做的。

如果您只需要将列表转换为计数图,请继续阅读。

您可以使用 Java 8 Streams API 在单个语句中将列表转换为计数映射:

final var list = List.of("12345", "34578", "12345", "98710", "12345");

final var counts = list.stream()
    .collect(Collectors.toMap(
        Function.identity(), // Map keys are list elements
        value -> 1, // Map values are counts, a single item counts "1"
        (count1, count2) -> count1 + count2 // On duplicate keys, counts are added
    ));

在底层,此解决方案使用哈希映射(元素到计数)作为数据结构。

您也可以使用groupingBy 收集器,正如Peter Lawrey 所建议的那样:

final var list = List.of("12345", "34578", "12345", "98710", "12345");

final var counts = list.stream()
    .collect(Collectors.groupingBy(
        Function.identity(), // Group the elements by equality relation
        Collectors.counting() // Map values are counts of elements in the equality groups
    ));

有时(在学习时)“手动”实现所有内容以理解算法是有益的。所以这里的版本没有 Java 8 的好东西,比如流、收集器和新的地图方法,比如 Map.compute()

final List<Stream> list = List.of("12345", "34578", "12345", "98710", "12345"); // Use ArrayList if you're below Java 9

final Map<String, Integer> counts = new HashMap<>();
for (final String item : list) {
    // Note: I'm deliberately NOT using Map.compute() here
    // to demonstrate how to do everything "manually"
    Integer count = counts.get(item);
    if (count == null) {
        count = 0;
    }
    counts.put(item, count + 1);
}

【讨论】:

  • Collectors.groupingBy(p -&gt; p, Collectors.counting());
  • “我故意不使用 Map.compute()”Map.merge 无论如何都会比Map.compute 更容易。
【解决方案2】:

假设您的列表是字符串(如果不是,您可能需要一个“比较器”)。循环整个列表,将元素添加到HashMap 和它们自己的计数器;但在此之前,请检查相关元素是否存在,并相应地更新计数器。

最终,Java 流也可以提供帮助。

【讨论】:

    【解决方案3】:

    您可以使用简单的Collections.frequency 方法来完成此操作。

    import java.util.List;
    import static java.util.Collections.frequency;
    
    List list = List.of("12345", "34578", "12345", "98710", "12345");
    System.out.println( frequency(list, "12345") );
    

    【讨论】:

      猜你喜欢
      • 2021-07-16
      • 1970-01-01
      • 2018-11-15
      • 2021-02-05
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多