在我的项目中,我使用Seq[Drone]
来跟踪世界中的无人机。它是一个功能项目,所以世界和无人机都是案例类的价值。
在世界process()
方法中,返回一个新的World
实例,其中包含该序列的转换版本,并且因为它是无序的,所以没有保证无人机以相同的顺序返回。这是设计初步实施的。
现在,现在是时候实施ID系统,以便可以单独分配动作(例如" d1移动到(4,6)")。这意味着无人机需要以保留" order"的方式存储。
我花了一些时间提出了几种方法,但首先,确定了ID 如何工作的方式。
Drone
类型没有ID - 这是一个仅由World
赋予意义的概念。我的Seq[Drone]
将成为Vector[(Int, Drone)]
。对无人机的引用将从world.drones(n)
更改为world.drones(n)._2
,这有很多原因。 ID可以通过world.drones(n)._1
访问。
我将名为D
的类型添加到(Int, Drone)
,并将Seq[Drone]
更改为Vector[D]
。我相信这与选项1有类似的问题,尽管我没有很多关于类型化的经验。
我制作case class D(id: Int, drone: Drone)
之类的内容并将Seq[Drone]
变为Vector[D]
作为选项2.这样做的好处是可以提供更好的通话(d.id
和{{ 1}}而不是元组语法),并且几乎可以用于元组(d.drone
vs D(1, Drone())
- 单个字符的区别)。
我的问题是:选项3是一个合适的解决方案吗?如果是这样,我将来会遇到哪些问题? (我设想一些工作来整理电话,但除此之外什么都没有。)如果没有,我可以通过哪些途径找到更适合的电话?
答案 0 :(得分:2)
所有3个选项几乎相同。 2元组实际上只是一个名为Tuple2
的案例类,其中Scala添加了一些语法糖,因此您可以编写(a, b)
而不是Tuple2(a,b)
。因此,考虑到这些选项,我会选择选项3,因为更具描述性的方法名称。事实上,由于这个原因,通常不鼓励使用元组。
但是还有另一种可能性,请使用Map[Int, Drone]
。这将为您提供开箱即用的一些功能(包括通过id和唯一性检查快速查找)并完成相同的操作,而无需定义您自己的新类型。
例如,您可以定义将无人机添加为:
def addDrone(drones: Map[Int, Drone], newDrone : Drone): Map[Int, Drone] = {
val id = (0 until drones.size).find(!drones.contains(_)).getOrElse(drones.size)
drones + (id -> newDrone)
}
并且释放id就像从地图中删除它一样简单。