Выберите элемент с максимальным вхождением в 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)));

но это слишком медленно. Можете ли вы предложить, что именно я должен использовать?

Update 1: использование вышеуказанного метода copyHighestCountFirst оказывается слишком медленным. В одном случае цикла он занимает 80 + миллисекунд против средних 40 миллисекунд, используя без него. В больших циклах я должен предпочесть простую итерацию?

Update 2: получил его, используя :

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

без почти нулевого влияния на производительность. Мне все еще интересно, есть ли лучший способ сделать это.

Sidenote : в 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 ответов


между вашим вопросом и другим ответом было много альтернатив, но многие из них, похоже, зависят от идеи, что .get(0) или .iterator().next() будет Вам наиболее частый элемент. Не будет!

Ваши только два достойных выбора Multisets.copyHighestCountFirst(bag).elementSet().iterator().next(), что расточительно, как вы говорите, или цикл через entrySet вручную и проверьте, чтобы увидеть, если это наиболее часто до сих пор.

вы должны подать запрос функции Guava для извлечения наиболее частый элемент. Я не могу обещать, что с ним случится, но оно того стоит.


одно альтернативное решение, которое не требовало бы явного цикла , но выполнялось бы в линейном времени в количестве различных элементов, что большинство этих других решений не может-было бы

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

из-за ваших изменений и формулировок неясно, чего вы хотите. Кроме того, используя myList как имя переменной, которое является multiset не является описательным - я буду использовать bag как переменное имя для multiset (это мешок в конце концов).

  1. "кажется, Multiset уже упорядочен в соответствии с частотами" - он упорядочен по частотам или нет?

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

    is [c0ffee x 2, abba, mfl x 3] потому что он использует порядок вставки, так что ваша коллекция мая быть упорядоченным должным образом по совпадению (я не знаю, есть ли здесь случай). Если вы не уверены в заказе, просто используйте

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

    что дает [mfl x 3, c0ffee x 2, abba]. С Multisets.copyHighestCountFirst возвращает неизменяемый multiset, вам не нужно использовать его в цикле, предполагая, что ваш multiset не изменяется. Если вы просто сделали глупый microbenchmark и увидели, что с помощью Multisets.copyHighestCountFirst в два раза медленнее, что означает 80 мс против 40 мс-забудьте об этом, потому что преждевременная оптимизация является корнем всех зло. Я предполагаю, что мы правильно составленного sortedBag на данный момент.

  2. из того, что я вижу, вы хотите количество наиболее распространенных элементов в сумке это просто:

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

    или если ваш multiset ImmutableMultiset:

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

    отметим, что sortedBag.entrySet() это коллекция Multiset.Entry который имеет как элемент, так и количество, поэтому выберите тот, который вы хотите.

  3. имея ImmutableMultiset позволяет использовать его ImmutableList вид, на который вы можете позвонить get(0) чтобы получить элемент:

    sortedBag.asList().get(0)
    

    который дает вам только элемент (здесь: строка) без счета, поэтому, если ваш план состоит в том, чтобы получить только элемент, который вы можете использовать asList() вместо того, чтобы играть с iterator.


я столкнулся с подобной проблемой сегодня, пытаясь найти простой, разумно эффективный способ найти элемент в Multiset с максимальным количеством. В будущем мы живем с Java 8, я смог изменить Луиса Вассермана решение в чистый один вкладыш:

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

это даст вам Multiset.Entry С максимальным количеством (при условии multiset не пуст), позволяя вам получить доступ к элементу или его количеству.