jas*_*son 12 haskell list edit
我知道xs !! n给了我列表中的第n个元素,但我不知道如何编辑该列表中的第n个元素.你能告诉我如何编辑列表中的第n个元素或至少给出一个提示吗?例如,如何将第二个元素'a'设为'e':['s','t','a','c','k']?谢谢.
Dav*_*rak 15
许多语言中的常见操作是分配给数组中的索引位置.在python中你可能会:
>>> a = [1,2,3,4,5]
>>> a[3] = 9
>>> a
[1, 2, 3, 9, 5]
Run Code Online (Sandbox Code Playgroud)
该
镜头包给出与此功能(.~)
操作.虽然与python不同,原始列表不会发生变异,而是返回一个新列表.
> let a = [1,2,3,4,5]
> a & element 3 .~ 9
[1,2,3,9,5]
> a
[1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
element 3 .~ 9
只是一个功能,(&)
操作员,镜头包的一部分
,只是反向功能应用.这里有更常见的功能应用.
> (element 3 .~ 9) [1,2,3,4,5]
[1,2,3,9,5]
Run Code Online (Sandbox Code Playgroud)
对任意嵌套Traversable
s 再次赋值再次完美.
> [[1,2,3],[4,5,6]] & element 0 . element 1 .~ 9
[[1,9,3],[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
要么
> set (element 3) 9 [1,2,3,4,5,6,7]
Run Code Online (Sandbox Code Playgroud)
或者,如果您想要影响多个元素,您可以使用:
> over (elements (>3)) (const 99) [1,2,3,4,5,6,7]
> [1,2,3,4,99,99,99]
Run Code Online (Sandbox Code Playgroud)
这不仅限于列表,但它适用于任何作为Traversable类型类实例的数据类型.
> import Data.Tree
> :{
let
tree = Node 1 [
Node 2 [Node 4[], Node 5 []]
, Node 3 [Node 6 [], Node 7 []]
]
:}
> putStrLn . drawTree . fmap show $ tree
1
|
+- 2
| |
| +- 4
| |
| `- 5
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ tree & element 1 .~ 99
1
|
+- 99
| |
| +- 4
| |
| `- 5
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ tree & element 3 .~ 99
1
|
+- 2
| |
| +- 4
| |
| `- 99
|
`- 3
|
+- 6
|
`- 7
> putStrLn . drawTree . fmap show $ over (elements (>3)) (const 99) tree
1
|
+- 2
| |
| +- 4
| |
| `- 5
|
`- 99
|
+- 99
|
`- 99
Run Code Online (Sandbox Code Playgroud)
fva*_*nee 12
因为Haskell是一种函数式语言,所以你不能"编辑"列表中的元素,因为一切都是不可变的.相反,您可以使用以下内容创建新列表:
take n xs ++ [newElement] ++ drop (n + 1) xs
Run Code Online (Sandbox Code Playgroud)
但是,不建议在Haskell中使用.有关更多信息,您可以看到这篇文章:Haskell替换列表中的元素
您无法编辑列表的第n个元素,值是不可变的.您必须创建一个新列表.但由于不变性,它可以在更改元素与原始列表之后共享该部分.
因此,如果要将变换应用于列表的第n个元素(并且在相同之前和之后具有部分),则有三个部分
front
element
back
.然后你要组装零件
front ++ transform element : back
Run Code Online (Sandbox Code Playgroud)
因此,仍然可以很好地掌握有趣的部分.
splitAt :: Int -> [a] -> ([a],[a])
Run Code Online (Sandbox Code Playgroud)
这样做,splitAt idx list
返回列表的第一部分,在索引idx
作为对的第一个组件之前,其余的作为第二部分,所以
changeNthElement :: Int -> (a -> a) -> [a] -> [a]
changeNthElement idx transform list
| idx < 0 = list
| otherwise = case spliAt idx list of
(front, element:back) -> front ++ transform element : back
_ -> list -- if the list doesn't have an element at index idx
Run Code Online (Sandbox Code Playgroud)
(注意:我已经开始计算元素为0,如果你想从1开始计数,你需要调整和使用idx-1
.)
令我惊讶的是以下方法尚未提及,因此我将添加它以供进一步参考:
replace index elem = map (\(index', elem') -> if index' == index then elem else elem') . zip [0..]
> replace 2 'e' "stack"
"steck"
Run Code Online (Sandbox Code Playgroud)
它处理索引超出范围的情况。
> replace (-1) 'z' "abc"
"abc"
> replace 0 'z' "abc"
"zbc"
> replace 2 'z' "abc"
"abz"
> replace 3 'z' "abc"
"abc"
Run Code Online (Sandbox Code Playgroud)
它并不比 splitAt 方法慢( O(2N) )。
归档时间: |
|
查看次数: |
16380 次 |
最近记录: |