Scala如何查找List匹配项 计算水果匹配得分返回对应人员
Scala 实现水果匹配得分映射
注意:Scala标准不可变
Map不支持重复键,你给出的示例中两个得分同为2的条目直接写入Map[Int, Person]时,后写入的Sarah会覆盖Simon的条目造成数据丢失,因此推荐使用Map[Int, List[Person]]结构按得分聚合人员,以下为具体实现。
核心逻辑
- 提前将客人携带的水果名称提取为集合,降低匹配查询的时间复杂度
- 对每位就餐人员,统计其携带水果中与客人水果重合的数量作为得分
- 按得分对人员做分组聚合,得到最终的得分-人员映射
完整实现代码
// 基础数据结构定义 case class Fruit(fruit: String) case class Person(str: String, value: List[Fruit]) object LunchSeatMatcher { def main(args: Array[String]): Unit = { // 初始化已知数据 val guest: Person = Person("Unknown", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes"))) val seatOwners = List( Person("Bob", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes"))), Person("Peter", List(Fruit("Apple"), Fruit("Pineapple"), Fruit("Mango"))), Person("Simon", List(Fruit("Apple"), Fruit("Pear"), Fruit("Mango"))), Person("sarah", List(Fruit("Pear"), Fruit("Grapes"), Fruit("Mango"))) ) // 提取客人的水果集合用于匹配 val guestFruits = guest.value.map(_.fruit).toSet // 单个人的得分计算逻辑:统计匹配的水果种类数 def calcMatchScore(person: Person): Int = person.value.map(_.fruit).count(guestFruits.contains) // 推荐写法:按得分分组,同得分人员存入列表,无数据丢失 val scoreToPeople: Map[Int, List[Person]] = seatOwners.groupBy(calcMatchScore) /* 输出结果: Map( 3 -> List(Person("Bob", List(Fruit("Apple"), Fruit("Pear"), Fruit("Grapes")))), 2 -> List(Person("Simon", List(Fruit("Apple"), Fruit("Pear"), Fruit("Mango"))), Person("sarah", List(Fruit("Pear"), Fruit("Grapes"), Fruit("Mango")))), 1 -> List(Person("Peter", List(Fruit("Apple"), Fruit("Pineapple"), Fruit("Mango")))) ) */ // 若严格按你给出的单Person映射结构写,会出现同得分覆盖问题 val scoreToSinglePerson: Map[Int, Person] = seatOwners.map(p => calcMatchScore(p) -> p).toMap /* 输出结果中2分仅保留最后一个sarah: Map( 3 -> Person("Bob", ...), 2 -> Person("sarah", ...), 1 -> Person("Peter", ...) ) */ } }
补充说明
- 当前实现按水果种类匹配计数,不考虑水果重复个数,和你给出的示例得分完全一致:Bob得3分、Simon和Sarah得2分、Peter得1分。
- 如果需要按水果个数计数(例如客人带2个苹果、对方带1个苹果仅算1次匹配,带2个算2次),可以将水果集合替换为频次Map,再做累加计数即可。
- 如果你确实需要支持一键多值的Map结构且不想用List聚合,可以使用可变的
scala.collection.mutable.MultiMap,但日常开发更推荐不可变的分组结果,无副作用、线程安全。
内容的提问来源于stack exchange,提问作者Ry2254
相关产品推荐
相关产品推荐

