Скажите, что у меня есть карта: Map[Int, String]
. Как бы получить значение [String]
с наименьшим ключом [Int]
. Я пытался реализовать это функционально, но просто не могу понять, как это сделать.Получить значение с наименьшим значением ключа с карты [Int, String]
ответ
Следующий код даст вам значение с наименьшим ключом (игнорируя некоторые угловые случаи).
def lowestKeyMember[A](m: Map[Int,A]): A = m(m.keys.min)
Это сломает связи произвольно и выбрасывает пустую карту. Если вам нужно делать эту операцию часто и/или на больших картах, вы должны посмотреть на SortedMap
.
Карты обычно не сортируются. Однако вы можете использовать SortedMap, тогда карта будет отсортирована, и первым значением будет голова. Все, что вам нужно сделать, это получить голову.
map.head()
Если вы используете отсортированную карту, она всегда сортируется. – ziggystar
Справа. Спасибо за напоминание :). Я внес изменения в свой ответ. –
Да ладно, люди! «Функционально» - это кодовое слово для «складывания».
scala> val m = Map(1->"eins",2->"zwei",3->"drei")
m: scala.collection.immutable.Map[Int,String] = Map(1 -> eins, 2 -> zwei, 3 -> drei)
scala> m.foldLeft(Int.MaxValue -> "") { case (min,p) => if (min._1 <= p._1) min else p }
res0: (Int, String) = (1,eins)
Но оператор с 8 символами?
Давайте посмотрим, достаточно ли парнеров? Не говорите мне ->
как -
и /:
как /
.
scala> (Int.MaxValue -> "" /: m) { case (min,p) => if (min._1 <= p._1) min else p }
<console>:9: error: missing arguments for method /: in trait TraversableOnce;
follow this method with `_' if you want to treat it as a partially applied function
(Int.MaxValue -> "" /: m) { case (min,p) => if (min._1 <= p._1) min else p }
^
О, ну, хорошо.
scala> ((Int.MaxValue -> "") /: m) { case (min,p) => if (min._1 <= p._1) min else p }
res2: (Int, String) = (1,eins)
Или
scala> import math.Ordering.Implicits._
import math.Ordering.Implicits._
scala> ((Int.MaxValue -> "") /: m) { case (min,p) if min <= p => min case (_, p) => p }
res5: (Int, String) = (1,eins)
Вариант _.keys.min
решения, которое работает с вариантами (т.е. не будет бросать на пустой карте):
scala> val a : Map[Int, String]=Map(1 -> "1", 2 -> "2")
a: Map[Int,String] = Map(1 -> 1, 2 -> 2)
scala> val b : Map[Int, String]=Map()
b: Map[Int,String] = Map()
scala> def valueForMinKey[K,V](a : Map[K,V])(implicit cmp : Ordering[K]) = a.keys.reduceOption(cmp.min(_, _)).map(a(_))
valueForMinKey: [K, V](a: Map[K,V])(implicit cmp: Ordering[K])Option[V]
scala> valueForMinKey(a)
res27: Option[String] = Some(1)
scala> valueForMinKey(b)
res28: Option[String] = None
В этом примере, неявный параметр cmp
будет удовлетворен Ordering.Int
. Пример будет работать с любой Картой, где ключи могут быть заказаны (и соответствующий имплиант может быть найден компилятором).
Если вы используете TreeMap, самая низкая клавиша всегда будет первой – Robert