Выберите элемент с максимальным вхождением в 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 (это мешок в конце концов).
-
"кажется, 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
на данный момент. -
из того, что я вижу, вы хотите количество наиболее распространенных элементов в сумке это просто:
int count = sortedBag.entrySet().iterator().next().getCount();
или если ваш multiset
ImmutableMultiset
:int count = sortedBag.entrySet().asList().get(0).getCount();
отметим, что
sortedBag.entrySet()
это коллекцияMultiset.Entry
который имеет как элемент, так и количество, поэтому выберите тот, который вы хотите. -
имея
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
не пуст), позволяя вам получить доступ к элементу или его количеству.