Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 组合列表函数_Scala - Fatal编程技术网

Scala 组合列表函数

Scala 组合列表函数,scala,Scala,下面的函数计算列表元素的可能组合 (1, 2), (1, 3), (1, 4) 不返回列表中相同的元素,也只返回唯一的元素: def combinations[T](l: List[T]): List[(T,T)] = l match { case Nil => Nil case h::Nil => Nil case h::t => t.map(x=>(h,x)) ++ combinations(t) } 列表(1,2,3)返回列表((1,2)

下面的函数计算列表元素的可能组合

(1, 2), (1, 3), (1, 4)
不返回列表中相同的元素,也只返回唯一的元素:

def combinations[T](l: List[T]): List[(T,T)] = l match {
    case Nil => Nil
    case h::Nil => Nil
    case h::t => t.map(x=>(h,x)) ++ combinations(t)
}
列表(1,2,3)返回列表((1,2)、(1,3)、(2,3))


这个解决方案(不是我的)很优雅,但我想知道它背后的直觉。代码中包含的列表元素是否有我不知道的通用属性?我知道这个解决方案为什么有效,但我不确定如何实现这个解决方案?

当您考虑如何手动构建所有组合时,这实际上是非常直观的。例如,以
列表(1、2、3、4)
为例。为了有条不紊地创建所有组合,我将获取列表中的第一个元素
1
,然后将其与所有剩余元素组合

(1, 2), (1, 3), (1, 4)
这些都是包含
1
的可能组合。现在,让我们找到所有包含
2
的组合,但不需要包含那些包含
1
的组合,因为我们已经有了它们。这意味着我们将使用列表中其余元素的组合

(2, 3), (3, 4)
然后使用
3

(3, 4)
你看到图案了吗?我们获取列表的第一个元素,然后将其与列表的所有剩余元素(尾部)配对。这就是代码的这一部分:

case h :: t => t.map(x => (h, x))
 //  1 :: List(2, 3, 4) => List((1, 2), (1, 3), (1, 4))
然后我们移动到列表的下一个元素,并执行相同的操作。这是递归步骤:
++compositions(t)
,并使用
++
聚合结果

如果我们从
1
开始,那么在封面下的第一个递归调用是
组合(列表(2,3,4))
,我们重复以下逻辑:

case h :: t => t.map(x => (h, x))
 //  2 :: List(3, 4) => List((2, 3), (3, 4))
最后:

case h :: t => t.map(x => (h, x))
 //  3 :: List(4) => List((3, 4))
因此,我们用
List((1,2),(1,3),(1,4))+++List((2,3),(3,4))+++List((3,4))

当然,在其他情况下,如果有零个或一个元素,就不能产生更多的组合:

case Nil => Nil
case h :: Nil => Nil
正如@0_uuuu所述,
h::Nil
实际上可以由
h::t
处理,因为我们将有:

case h :: t => t.map(x => (h, x)) ++ combinations(t)
//        ^ Nil    ^ Nil maps to Nil          ^ Will hit the first case on the next call, which is also Nil

当您考虑如何手动构建所有组合时,这实际上是非常直观的。例如,以
列表(1、2、3、4)
为例。为了有条不紊地创建所有组合,我将获取列表中的第一个元素
1
,然后将其与所有剩余元素组合

(1, 2), (1, 3), (1, 4)
这些都是包含
1
的可能组合。现在,让我们找到所有包含
2
的组合,但不需要包含那些包含
1
的组合,因为我们已经有了它们。这意味着我们将使用列表中其余元素的组合

(2, 3), (3, 4)
然后使用
3

(3, 4)
你看到图案了吗?我们获取列表的第一个元素,然后将其与列表的所有剩余元素(尾部)配对。这就是代码的这一部分:

case h :: t => t.map(x => (h, x))
 //  1 :: List(2, 3, 4) => List((1, 2), (1, 3), (1, 4))
然后我们移动到列表的下一个元素,并执行相同的操作。这是递归步骤:
++compositions(t)
,并使用
++
聚合结果

如果我们从
1
开始,那么在封面下的第一个递归调用是
组合(列表(2,3,4))
,我们重复以下逻辑:

case h :: t => t.map(x => (h, x))
 //  2 :: List(3, 4) => List((2, 3), (3, 4))
最后:

case h :: t => t.map(x => (h, x))
 //  3 :: List(4) => List((3, 4))
因此,我们用
List((1,2),(1,3),(1,4))+++List((2,3),(3,4))+++List((3,4))

当然,在其他情况下,如果有零个或一个元素,就不能产生更多的组合:

case Nil => Nil
case h :: Nil => Nil
正如@0_uuuu所述,
h::Nil
实际上可以由
h::t
处理,因为我们将有:

case h :: t => t.map(x => (h, x)) ++ combinations(t)
//        ^ Nil    ^ Nil maps to Nil          ^ Will hit the first case on the next call, which is also Nil

使用
列表定义函数/递归解决方案时,最简单的方法是涵盖发生的基本情况。然后定义部分解决方案并将它们添加到一起

您希望在输出中有成对的元素,因此您首先会发现,对于空列表(
Nil
)或仅包含单个元素(
h::Nil
)的列表,没有部分解决方案,因此这两种情况的结果是
Nil
。最后一种情况是头部元素
h
和非空尾部。因此,使用
map
函数为每个尾部元素生成所有
h
对,并对尾部递归重复

请注意,从技术上讲,中间的情况是不相关的。以下几点就足够了:

def combinations[A](xs: List[A]): List[(A, A)] = xs match {
  case Nil => Nil
  case h :: t => t.map(h -> _) ++ combinations(t)
}

使用
列表定义函数/递归解决方案时,最简单的方法是涵盖发生的基本情况。然后定义部分解决方案并将它们添加到一起

您希望在输出中有成对的元素,因此您首先会发现,对于空列表(
Nil
)或仅包含单个元素(
h::Nil
)的列表,没有部分解决方案,因此这两种情况的结果是
Nil
。最后一种情况是头部元素
h
和非空尾部。因此,使用
map
函数为每个尾部元素生成所有
h
对,并对尾部递归重复

请注意,从技术上讲,中间的情况是不相关的。以下几点就足够了:

def combinations[A](xs: List[A]): List[(A, A)] = xs match {
  case Nil => Nil
  case h :: t => t.map(h -> _) ++ combinations(t)
}

问题是什么?要解释为什么会这样?@0\uuuu请查看更新问题是什么?要解释为什么会这样?@0\uuuu请查看更新