在Multiset中选择具有最大出现次数的元素

时间:2013-05-23 14:00:26

标签: java collections guava

我可能想将问题改为“我如何选择Multiset中的第一项?”因为似乎Multiset已按照频率排序。

我有一个Multiset myList = Multiset.create();

[maa00 mfnt11 malignlft mbold mlt18 mfl x 3, caa00 cfnt11 calignlft cbold clt17 cfl]

我找不到像myList.getIndex(0)这样的方法。请注意,最后,我需要具有最大频率的元素数。

这是否有任何一个班轮?或者我必须做那个迭代?

更新: 我使用以下方式获得最高频率:

myList.count(Multisets.copyHighestCountFirst(myList).asList().get(0)));

但这太慢了。你能告诉我,我到底应该使用什么?

更新1:使用上面的copyHighestCountFirst方法证明太慢了。在循环的一个实例中,在没有它的情况下使用80 +毫秒而不是平均40毫秒。 在大循环中,我应该更喜欢简单的迭代吗?

更新2:使用以下工具:

myList.count(myList.entrySet().iterator().next().getElement())

对性能几乎没有影响。我仍然想知道是否有更好的方法来做到这一点。

旁注:在Python中,我做了同样的事情:

j = defaultdict(int)
for k in clList:
    j[k] +=1
result1 = max(j.iteritems(), key=lambda x:x[1]) //count of frequency of item with max count

4 个答案:

答案 0 :(得分:14)

在您的问题与发布的其他答案之间存在很多替代方案,但其中许多似乎依赖于.get(0).iterator().next()会让您获得最频繁的观点元件。它不会!

你唯一的两个不错的选择是Multisets.copyHighestCountFirst(bag).elementSet().iterator().next(),这就像你说的那样浪费,或者手动循环entrySet并检查每一个是否是目前为止最常见的。

您应该提交Guava功能请求以提取最常用的元素。我不能保证会发生什么,但值得请求。

答案 1 :(得分:4)

一个不需要显式循环的替代解决方案 - 但是会在不同元素的数量中以线性时间运行,而其他大多数解决方案都不能 - 将是

Ordering.natural().onResultOf(new Function<Multiset.Entry<Foo>, Integer>() {
  public Integer apply(Multiset.Entry<Foo> entry) {
    return entry.getCount();
  }
}.max(multiset.entrySet()).getElement();

答案 2 :(得分:2)

由于您的编辑和短语,您不清楚自己想要什么。另外,使用myList作为多重集的变量名称不是描述性的 - 我将使用bag作为multiset的变量名(毕竟它是包)。

  1. 似乎Multiset已按照频率进行排序” - 它是否根据频率排序?

    ImmutableMultiset<String> bag = ImmutableMultiset.of(
        "c0ffee", "abba", "mfl", "mfl", "mfl", "c0ffee");
    

    [c0ffee x 2, abba, mfl x 3],因为它使用了广告订单,因此您的广告可能会按顺序正确排序(我不知道这是否属于这种情况)。如果您不确定订购,请使用

     ImmutableMultiset<String> sortedBag = Multisets.copyHighestCountFirst(bag)
    

    给出了[mfl x 3, c0ffee x 2, abba]。由于Multisets.copyHighestCountFirst返回不可变多重集,因此假设您的多重集不会更改,则不必在循环中使用它。如果你只是做了一个愚蠢的微基准测试并且看到使用Multisets.copyHighestCountFirst的速度是80毫秒和40毫秒的两倍 - 请忘记它,因为premature optimization is the root of all evil。我认为此时我们已正确订购sortedBag

  2. 从我看到你想要的包中最常见元素的数量简单地说:

    int count = sortedBag.entrySet().iterator().next().getCount();
    

    或者您的多重集合是ImmutableMultiset

    int count = sortedBag.entrySet().asList().get(0).getCount();
    

    请注意,sortedBag.entrySet()Multiset.Entry的集合,其中包含元素和计数,因此请选择一个。

  3. ImmutableMultiset允许您使用ImmutableList视图,您可以在其中调用get(0)来获取元素:

    sortedBag.asList().get(0)
    

    只给你一个没有计数的元素(这里是一个字符串),所以如果你的计划是只获取元素,你可以使用asList()而不是使用迭代器。

答案 3 :(得分:2)

今天我遇到了类似的挑战,试图找到一种简单,合理有效的方法来查找Multiset中具有最大计数的元素。在未来我们生活在Java 8中,我能够将Louis Wasserman的solution修改成干净的一行:

multiset.entrySet().stream().max(Ordering.natural().onResultOf(Multiset.Entry::getCount)).get();

这将为Multiset.Entry提供最大数量(假设multiset不为空),允许您访问元素或其计数。