Scala 对使用 map 和 flatten

Scala pairs using map and flatten

我正在解决一个问题,取两个列表,例如 (1,2,3) 和 (a,b) 和 return 一个列表 ((1,a)(1,b )(2,a)(2,b)(3,a)(3,b)) 仅使用映射和展平。

这道题需要我定义一个函数如下:

def product[A](xs: List[A], ys: List[A])= {

并在此函数内得到结果。我是 Scala 的新手,我习惯了 python 和 java.

这样的语言

我已经走到这一步了:

def product[A](xs: List[A], ys: List[A])= {  
    for(y <- ys){
   println(xs.map(x=> (x,y)))  
    }
  }

这将 return 像这样:

列表((1,a), (2,a), (3,a))

列表((1,b), (2,b), (3,b))

我不确定现在如何合并这些列表。在 python 中,我会做一些事情,比如创建一个新的列表变量,将这两个列表附加到该列表,然后将其展平,这样我就有了一个列表。但是,我对 scala 感到很困惑,因为它似乎不允许我在函数中定义新变量。此时我如何合并这些列表并将它们展平?

仅使用映射和展平的产品列表

val nums = List(1, 2, 3)
val chars = List('a', 'b')

nums.map { a => chars.map { b => (a, b) } }.flatten

Scala REPL

scala> nums.map(a => chars.map(b => (a, b)))
res5: List[List[(Int, Char)]] = List(List((1, 'a'), (1, 'b')), List((2, 'a'), (2, 'b')), List((3, 'a'), (3, 'b')))
scala> nums.map(a => chars.map(b => (a, b))).flatten
res6: List[(Int, Char)] = List((1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b'))

可以使用flatMap和地图组合构建产品列表

nums.flatMap { a => chars.map { b => (a, b) }} 

也可以使用理解来构建产品列表

for {a <- nums; b <- chars} yield (a, b)

Scala REPL

scala> val nums = List(1, 2, 3)
val nums: List[Int] = List(1, 2, 3)

scala> val chars = List('a', 'b')
chars: List[Char] = List('a', 'b')

scala> nums.flatMap { a => chars.map { b => (a, b) }}
res2: List[(Int, Char)] = List((1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b'))

scala> for {a <- nums; b <- chars} yield (a, b)
res3: List[(Int, Char)] = List((1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b'))

您可以使用理解来解决它。它实际上是 syntactic sugar for map and flatMap:

def product[A](xs: List[A], ys: List[A])= {
    for {
      x <- xs
      y <- ys
    } yield {
      x -> y
    }
}

For-comprehensions 是 Scala 惯用的实现方式。更具可读性和可维护性,底层操作仍然是mapflatMap。事实上,即使对于不是集合但仍然具有 mapflatMap 的类型,也很常见地用于推导式 (Futures、Options、Trys等)

编辑

如果您想继续您的解决方案并保存列表并合并它们,您必须删除 println 并添加 yield,然后展平原来的主列表创建:

def product[A](xs: List[A], ys: List[A]) = {
  for (y <- ys) yield {
    xs.map(x => (x, y))
  }
}

val res = product(List(1, 2, 3), List("a", "b"))

println(res.flatten)
val ls1 = List(1,2,3) 
val ls2 = List('a','b') 
def product[A](xs: List[A], ys: List[A])= xs.map(x => ys.map((x,_))).flatten 

product(ls1,ls2)