Хорошо ли определена функция take на карте Scala? - PullRequest
0 голосов
/ 22 сентября 2018

Безопасно ли использовать функцию take на Scala Map?Я думал, что Map не были упорядочены, так что myMap.take(2) вернет 2 случайных элемента myMap.Но тестирование на интерпретаторе заставляет меня чувствовать, что это безопасно:

scala> val z = Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40)
z: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40)

scala> z.take(2)
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20)

scala> z.take(2)
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20)

scala> z.take(2)
res3: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20)

scala> z.take(2)
res4: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20)

Итак, безопасно ли использовать take на Map, или мне нужно использовать ListMap?

Ответы [ 4 ]

0 голосов
/ 22 сентября 2018

Точно ли определена функция take на Scala Map?

Это зависит от вашего точного определения "четко определенного", но я бы сказал, что да, для большинства распространенныхинтерпретации «четко определенные», они четко определены.

Документация четко перечисляет все возможные результаты для всех возможных входных данных, и нет никаких двусмысленных или неопределенных входных данных.Охватываются все угловые случаи:

  • Если в коллекции меньше n элементов, будет возвращена вся коллекция.
  • Если n отрицательно, пустая коллекция будет
  • Если коллекция не упорядочена, будут возвращены произвольные элементы.

Безопасна ли функция take для использования в Scala Map?

Это зависит от вашего точного определения «безопасно», но я бы сказал, что да, для большинства распространенных интерпретаций «безопасно», это безопасно.

  • Статически безопасен для типов.
  • Динамически безопасен для типов.
  • Он не вызывает исключения.

Я думал, что Map s были неупорядочены, так что myMap.take(2) вернет 2 случайных элемента myMap.

No.Документация гласит:

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

Это означает, что произвольные элементы будут возвращены, а неслучайные.

0 голосов
/ 22 сентября 2018

Не зная точно, чего вы пытаетесь достичь, вы можете рассмотреть возможность использования SortedMap, который гарантирует, что ключи отсортированы по порядку.Рассмотрим следующие два примера в Scala REPL :

scala> val z = Map(4 -> 40, 3 -> 30, 1 -> 10, 2 -> 20)
z: scala.collection.immutable.Map[Int,Int] = Map(4 -> 40, 3 -> 30, 1 -> 10, 2 -> 20)

scala> z.take(2)
res0: scala.collection.immutable.Map[Int,Int] = Map(4 -> 40, 3 -> 30)

scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap

scala> val zs = SortedMap(4 -> 40, 3 -> 30, 1 -> 10, 2 -> 20)
zs: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40)

scala> zs.take(2)
res1: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 10, 2 -> 20)

Как указывало @jwvh, в обычном Map нет определенного порядка, но этот порядок фиксирован после определения,таким образом, вы всегда будете получать одни и те же члены, возвращенные для .take(2) при одном и том же экземпляре карты.Однако то, какие значения вы получите, будет зависеть от порядка создания карты.

Между тем, в SortedMap ключи всегда упорядочены, поэтому при использовании элементов .take(2) вывсегда получат одинаковые два элемента, независимо от порядка определения: те, которые имеют два нижних значения ключа.

Обратитесь к справке по методу take для получения дополнительной информации.

0 голосов
/ 22 сентября 2018

Неизменяемые карты в Scala имеют специальные подтипы от 0 до 4 элементов, которые вы можете увидеть в коде в качестве оптимизации.Как это случается, Map.apply с максимум 4 аргументами создает экземпляр одного из этих классов, поэтому итерирование всегда будет производить элементы в порядке, переданном Map.apply.

0 голосов
/ 22 сентября 2018

Скорее всего, вы будете получать одни и те же 2 каждый раз, когда вы take(2), но пока неизвестно, какие 2 вы получите в первую очередь.

val y = Map(1 -> 10, 2 -> 20, 3 -> 30, 4 -> 40, 5 -> 5)
y.take(2)  //res0: Map[Int,Int] = Map(5 -> 5, 1 -> 10)
...