Scala地图上的Take函数定义是否正确?

时间:2018-09-21 23:20:04

标签: scala scala-collections take

在Scala learning_rate = tf.train.exponential_decay(learning_rate=0.1, global_step=tf.train.get_or_create_global_step(), decay_steps=100, decay_rate=0.96) optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate) estimator = tf.estimator.DNNClassifier( feature_columns=..., hidden_units=..., n_classes=..., model_dir=..., optimizer=optimizer) tf.estimator.train_and_evaluate( estimator=estimator, train_spec=..., eval_spec=...) 上可以安全使用take函数吗?我认为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

4 个答案:

答案 0 :(得分:3)

每次take(2),您很可能会获得相同的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)

答案 1 :(得分:3)

在不完全知道要实现的目标的情况下,您可能需要考虑使用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元素时,无论定义顺序如何,都将始终获得相同的两个元素:具有最低的两个键值。

有关更多信息,请参考help on the take method

答案 2 :(得分:1)

Scala中的不可变映射具有0到4个元素的特殊子类型,you can see in the code作为优化。碰巧,Map.apply最多包含4个参数,将生成这些类之一的实例,因此对其进行迭代将始终按传递给Map.apply的顺序生成元素。

答案 3 :(得分:-1)

  

Scala Map上的take函数定义正确吗?

这取决于您对“定义明确”的确切定义,但我认为,是的,对于“定义明确”的大多数常见解释,它都是定义明确的。

The documentation清楚列出所有可能输入的所有可能结果,并且没有模棱两可或未指定的输入。涵盖了所有极端情况:

  • 如果集合中的元素少于n,则将返回整个集合。
  • 如果n为负,将返回一个空集合。
  • 如果集合是无序的,则将返回任意元素。
  

在Scala take上可以安全使用Map函数吗?

这取决于您对“安全”的确切定义,但是我认为,是的,对于“安全”的大多数常见解释,它是安全的。

  • 这是静态类型安全的。
  • 它是动态类型安全的。
  • 它不会引发异常。
  

我认为Map是无序的,所以myMap.take(2)将返回myMap的2个随机元素。

不。该文档说:

  

注意:对于不同的运行,可能会返回不同的结果,除非订购了基础的收集类型。

这意味着将返回任意元素,而不是随机元素。