У меня есть список, похожий по концепции на следующий:
val selectedValues = listOf("Apple", "Apple", "Apple", "Grape", "Grape", "Cherry")
Мне нужен способ сгруппировать и отсортировать его, чтобы я получил что-то вроде этого:
Яблоко: 3
Виноград: 2
Вишня: 1
Я немного продвинулся с ответом это, но я хочу, чтобы он был упорядочен по количеству (от большей части к меньшей), и я не могу понять, как туда добраться.
Я чувствую, что ответ, который я опубликовал, приближает меня очень к тому, что я хочу, но мне просто нужно выяснить, как заставить его работать так, как мне нужно, и я просто упираюсь в стену и нуждаюсь в небольшой помощи, поскольку я все еще довольно новичок в Kotlin.
Вы можете попробовать что-то вроде этого:
fun main(args : Array<String>) {
val selectedValues = listOf("Apple", "Apple", "Apple", "Grape", "Grape", "Cherry")
val solution = selectedValues
.groupBy { it }
.mapValues { it.value.size }
.toList()
.sortedByDescending { (_, value) -> value }
.toMap()
println(solution)
}
Это вернет вас
{Apple=3, Grape=2, Cherry=1}
что, я думаю, является (более или менее) тем, что вам нужно.
@Eman просто вставь .take(3)
между .sortedByDescending
и .toMap
.
спасибо, вы оба, что сделали свое дело.
Если вы хотите немного поумнеть, вы можете использовать Группировка, который позволяет вам выполнять операцию группировки и складывания, то есть группировать кучу вещей, а затем превращать каждую группу в результат — есть операция eachCount()
, которая превращает каждую группу в счет:
selectedValues.groupingBy { it }.eachCount()
.entries
.sortedByDescending { it.value }
.take(3) // they're still Entry pairs here, so you can toMap() if you need one
.run(::println)
Подход Стефано является наиболее общим (и определенно то, что я бы выбрал, если вы все еще начинаете), но есть и некоторые специальные инструменты для некоторых сценариев (возможно, с некоторой оптимизацией производительности, происходящей под капотом).
Существует также подход «создайте свою собственную карту подсчетов»:
// this is basically the same as "val newMap, stuff.forEach { update count in newMap }"
selectedValues.fold(mutableMapOf<String, Int>()) { counts, item ->
counts.apply { put(item, getOrDefault(item, 0) + 1) }
}
я думаю, что это то, как работает комбинация groupingBy().eachCount()
выше - вместо создания карты списков ("Apple"=["Apple", "Apple", "Apple"]
и т. д.), а затем создания карты целых чисел из нее, вы просто создаете Map<String, Int>
из исходного исходного списка.
Что бы ни было проще всего, вам нужно беспокоиться об эффективности только тогда, когда вы имеете дело с большим количеством вещей, а Kotlin позволяет вам писать хорошо читаемые операции с его основными функциями. Просто подумал, что дам вам представление о некоторых вариантах, которые у вас есть, так как вы немного боролись, на случай, если это поможет некоторым вещам щелкнуть!
Я ценю ответ, ответ Стефано соответствует тому, как я сделал бы это на С#, откуда я родом, но я ценю и другие способы добраться туда.
это действительно помогает, одна маленькая вещь, которую я хотел бы получить только 3 лучших, поэтому, если здесь около 20 записей, мне просто нужны 3 верхних значения.