9

我可能想将问题改写为“如何选择 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

4 回答 4

15

在您的问题和发布的其他答案之间有很多替代方案,但其中许多似乎取决于.get(0).iterator().next()将使您获得最常见元素的想法。它不会!

您仅有的两个不错的选择是Multisets.copyHighestCountFirst(bag).elementSet().iterator().next(),正如您所说的那样浪费,或者entrySet手动循环并检查每个选项,看看它是否是迄今为止最频繁的。

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

于 2013-05-24T19:27:21.460 回答
5

今天我遇到了类似的挑战,试图找到一种简单、合理有效的方法来查找 aMultiset中具有最大计数的元素。在我们使用 Java 8 的未来,我能够将 Louis Wasserman 的解决方案修改为一个干净的内衬:

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

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

于 2018-04-04T21:30:09.780 回答
4

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

Ordering.natural().onResultOf(new Function<Multiset.Entry<Foo>, Integer>() {
  public Integer apply(Multiset.Entry<Foo> entry) {
    return entry.getCount();
  }
}.max(multiset.entrySet()).getElement();
于 2013-05-24T23:44:23.920 回答
2

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

  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 毫秒的两倍——忘记它,因为过早的优化是万恶之源。我想我们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()而不是使用迭代器。

于 2013-05-23T15:23:15.223 回答