2013-06-19 3 views
3

Скажите, что у меня есть карта: Map[Int, String]. Как бы получить значение [String] с наименьшим ключом [Int]. Я пытался реализовать это функционально, но просто не могу понять, как это сделать.Получить значение с наименьшим значением ключа с карты [Int, String]

+1

Если вы используете TreeMap, самая низкая клавиша всегда будет первой – Robert

ответ

4

Следующий код даст вам значение с наименьшим ключом (игнорируя некоторые угловые случаи).

def lowestKeyMember[A](m: Map[Int,A]): A = m(m.keys.min) 

Это сломает связи произвольно и выбрасывает пустую карту. Если вам нужно делать эту операцию часто и/или на больших картах, вы должны посмотреть на SortedMap.

2

Карты обычно не сортируются. Однако вы можете использовать SortedMap, тогда карта будет отсортирована, и первым значением будет голова. Все, что вам нужно сделать, это получить голову.

map.head() 
+0

Если вы используете отсортированную карту, она всегда сортируется. – ziggystar

+0

Справа. Спасибо за напоминание :). Я внес изменения в свой ответ. –

2

Да ладно, люди! «Функционально» - это кодовое слово для «складывания».

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) 
2

Вариант _.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. Пример будет работать с любой Картой, где ключи могут быть заказаны (и соответствующий имплиант может быть найден компилятором).