如何在Haskell中列出所有可能替换的项目?
我的输入是一个任意列表,例如如何在Haskell中列出所有可能替换的项目?,haskell,Haskell,我的输入是一个任意列表,例如 ["a","b","c"] 还有另一个列表元素,比如说“z”。我希望输出看起来像: [["z","b","c"],["a","z","c"],["a","b","z"]] 我该怎么做 replace :: [a] -> a -> [[a]] replace [] _special = [] replace (x:xs) special = (special:xs) : map (x:) (replace xs special) 测试: 说
["a","b","c"]
还有另一个列表元素,比如说“z”
。我希望输出看起来像:
[["z","b","c"],["a","z","c"],["a","b","z"]]
我该怎么做
replace :: [a] -> a -> [[a]]
replace [] _special = []
replace (x:xs) special = (special:xs) : map (x:) (replace xs special)
测试:
说明:
我们希望生成所有列表,其中只有一个元素被特殊的元素替换
如果列表为空,则无法插入special
,因此我们不返回任何选项
如果列表改为x:xs
,一个选项是替换x
并获得special:xs
。其他选项可以通过递归方式计算,在尾部xs
中插入special
,最后在每个选项前面插入x
测试:
说明:
我们希望生成所有列表,其中只有一个元素被特殊的元素替换
如果列表为空,则无法插入special
,因此我们不返回任何选项
如果列表改为x:xs
,一个选项是替换x
并获得special:xs
。其他选项可以通过递归地采取任何方式来计算,在尾部插入special
,最后在每个前面插入x
;你能做的最好的,渐进的,是
replace x xs = zipWith f (inits xs) (dropLast $ tails xs)
where
f front (_ : rear) = front ++ x : rear
dropLast [] = []
dropLast [_] = []
dropLast (x:xs) = x : dropLast xs
注:这仅适用于base 4.7.0.2或更高版本(GHC 7.8.4或更高版本)
使用tail
而不是dropLast
演示一种更干净的方法
这里棘手的部分隐藏在inits
中,在最近的版本中,inits非常高效且懒惰
如果你真的想让这个操作快速,你必须放弃列表,而使用其他的表示法
import Data.Sequence
replace :: a -> Seq a -> Seq (Seq a)
replace x xs = mapWithIndex f xs
where
f i _ = update i x xs
没有有效的方法来处理列表;你能做的最好的,渐进的,是
replace x xs = zipWith f (inits xs) (dropLast $ tails xs)
where
f front (_ : rear) = front ++ x : rear
dropLast [] = []
dropLast [_] = []
dropLast (x:xs) = x : dropLast xs
注:这仅适用于base 4.7.0.2或更高版本(GHC 7.8.4或更高版本)
使用tail
而不是dropLast
演示一种更干净的方法
这里棘手的部分隐藏在inits
中,在最近的版本中,inits非常高效且懒惰
如果你真的想让这个操作快速,你必须放弃列表,而使用其他的表示法
import Data.Sequence
replace :: a -> Seq a -> Seq (Seq a)
replace x xs = mapWithIndex f xs
where
f i _ = update i x xs
这看起来像是一个家庭作业问题,所以这个答案可能对您没有帮助,但我喜欢使用数据列表中的inits
和tails
来解决这类问题
看看inits
和tail.tails
的工作原理:
as = inits [1..3] = [ [], [1], [1,2], [1,2,3] ]
bs = tail (tails [1..3]) = [ [2,3], [3], [] ]
cs = [1..3] = [ 1, 2, 3]
许多这类问题都是这些列表的三向压缩功能。例如,此问题的解决方案是:
[ a ++ "z" ++ b | (a,b) <- zip as bs ]
[a++“z”++b|(a,b)这看起来像是一个家庭作业问题,所以这个答案可能对您没有帮助,但我喜欢使用数据列表中的inits
和tails
来解决这类问题
看看inits
和tail.tails
的工作原理:
as = inits [1..3] = [ [], [1], [1,2], [1,2,3] ]
bs = tail (tails [1..3]) = [ [2,3], [3], [] ]
cs = [1..3] = [ 1, 2, 3]
许多此类问题都是这些列表的3向zip功能。例如,解决此问题的方法是:
[ a ++ "z" ++ b | (a,b) <- zip as bs ]
[a++“z”++b|(a,b)为什么效率低下?在任何情况下,都必须复制替换元素之前的列表单元格,而元素之后的尾部可以与输入列表共享,解决方案就是这样做的。@D如果看起来是O(n^2),这是渐近最优的。我忽略了什么吗?还有更有效的方法吗?如果将null
映射到结果列表上,则需要O(n^2)要计算。您可以使其更增量;最简单的方法是使用base 4.7.0.2或更高版本,将inits
压缩为tails
。为什么效率低下?在任何情况下,都必须复制替换元素之前的列表单元格,而在元素之后,tails可以与输入列表共享,解决方案就是这样做的。@dfeuer它看起来是O(n^2),这是渐近最优的。我忽略了什么吗?还有更有效的方法吗?如果你把null
映射到结果列表上,它将需要O(n^2)来计算。你可以使它更递增;最简单的方法,使用base 4.7.0.2或更高版本,是用尾部压缩inits
。