如何在 Scala 中创建查找映射

发布于 2024-11-25 22:51:02 字数 529 浏览 0 评论 0原文

虽然我知道有几种方法可以做到这一点,但我最感兴趣的是找到最惯用和最实用的 Scala 方法。

给出以下陈词滥调的示例:

case class User(id: String)
val users = List(User("1"), User("2"), User("3"), User("4")) 

创建 user.id 的不可变查找映射的最佳方法是什么 -> User 以便我可以通过 user.id 执行快速查找。

在Java中,我可能会使用Google-Collection的 Maps.uniqueIndex 尽管我不太关心它的独特属性。

While I know there's a few ways to do this, I'm most interested in finding the most idiomatic and functional Scala method.

Given the following trite example:

case class User(id: String)
val users = List(User("1"), User("2"), User("3"), User("4")) 

What's the best way to create an immutable lookup Map of user.id -> User so that I can perform quick lookups by user.id.

In Java I'd probably use Google-Collection's Maps.uniqueIndex although its unique property I care less about.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

眼中杀气 2024-12-02 22:51:09

如果您想使用数字索引:

scala> users.map (u=> u.id.toInt -> u).toMap 
res18: scala.collection.immutable.Map[Int,User] =
  Map((1,User(1)), (2,User(2)), (3,User(3)))

If you would like to use a numeric index:

scala> users.map (u=> u.id.toInt -> u).toMap 
res18: scala.collection.immutable.Map[Int,User] =
  Map((1,User(1)), (2,User(2)), (3,User(3)))
演多会厌 2024-12-02 22:51:09

映射也是函数,它们的 apply 方法提供对与特定键关联的值的访问(或者对于未知键抛出 NoSuchElementException ),因此这使得查找语法非常干净。遵循 Dan Simon 的答案并使用语义上更有意义的名称:

scala> val Users = users map {u  => (u.id, u)} toMap      
Users: scala.collection.immutable.Map[String,User] = Map((1,User(1)), (2,User(2)), (3,User(3)))

然后提供以下查找语法:

scala> val user2 = Users("2")
user2: User = User(2)

Maps are functions too, their apply method provides access to the value associated with a particular key (or a NoSuchElementException is thrown for an unknown key) so this makes for a very clean lookup syntax. Following on from Dan Simon's answer and using a more semantically meaningful name:

scala> val Users = users map {u  => (u.id, u)} toMap      
Users: scala.collection.immutable.Map[String,User] = Map((1,User(1)), (2,User(2)), (3,User(3)))

which then provides the following lookup syntax:

scala> val user2 = Users("2")
user2: User = User(2)
未央 2024-12-02 22:51:08

如果您确定所有 ID 都是唯一的,则规范的方式

users.map(u => (u.id, u)).toMap

正如 @Dan Simon 所说。但是,如果您不确定所有 ID 都是唯一的,那么规范的方法是:

users.groupBy(_.id)

这将生成从用户 ID 到共享该 ID 的用户列表的映射。

因此,有一种替代的不完全规范的方法来生成从 ID 到单个用户的映射:

users.groupBy(_.id).mapValues(_.head)

对于想要避免创建列表映射或列表然后变成映射的中间步骤的专家用户,如果有一种简单的方法的话,有一个方便的 scala.collection.breakOut 方法可以构建您想要的类型。不过,它需要知道类型,因此这可以解决问题:(

users.map(u => (u.id,u))(collection.breakOut): Map[String,User]

您也可以分配给指定类型的 var 或 val。)

If you're sure all IDs are unique, the canonical way is

users.map(u => (u.id, u)).toMap

as @Dan Simon said. However, if you are not sure all IDs are unique, then the canonical way is:

users.groupBy(_.id)

This will generate a mapping from user IDs to a list of users that share that ID.

Thus, there is an alternate not-entirely-canonical way to generate the map from ID to single users:

users.groupBy(_.id).mapValues(_.head)

For expert users who want to avoid the intermediate step of creating a map of lists, or a list which then gets turned into a map, there is the handy scala.collecion.breakOut method that builds the type that you want if there's a straightforward way to do it. It needs to know the type, though, so this will do the trick:

users.map(u => (u.id,u))(collection.breakOut): Map[String,User]

(You can also assign to a var or val of specified type.)

〃温暖了心ぐ 2024-12-02 22:51:08

将 List 转换为 Map 并将其用作函数:

  case class User(id: String)
  val users = List(User("1"), User("2"), User("3"))

  val usersMap = users map { case user @ User(id) => id -> user } .toMap

  usersMap("1")    // Some(User("1"))
  usersMap("0")    // None

Convert the List into a Map and use it as a function:

  case class User(id: String)
  val users = List(User("1"), User("2"), User("3"))

  val usersMap = users map { case user @ User(id) => id -> user } .toMap

  usersMap("1")    // Some(User("1"))
  usersMap("0")    // None
呢古 2024-12-02 22:51:07

您可以将用户保留在列表中并使用 list.find:

users.find{_.id == "3"} //returns Option[User], either Some(User("3")) or None if no such user

或者如果您想使用映射,请将用户列表映射到二元组列表,然后使用 toMap 方法:

val umap = users.map{u => (u.id, u)}.toMap

这将返回不可变的 Map[String ,用户],然后您可以使用

umap contains "1" //return true

umap.get("1") //returns Some(User("1"))

You can keep the users in a List and use list.find:

users.find{_.id == "3"} //returns Option[User], either Some(User("3")) or None if no such user

or if you want to use a Map, map the list of users to a list of 2-tuples, then use the toMap method:

val umap = users.map{u => (u.id, u)}.toMap

which will return an immutable Map[String, User], then you can use

umap contains "1" //return true

or

umap.get("1") //returns Some(User("1"))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文