我目前正在尝试找出遍历列表的最佳方法。我说的穿越是什么意思?
例子:
我有一个用户列表:
userList : List User
userList =
[user, user, user, user]
Run Code Online (Sandbox Code Playgroud)
我有一个 currentUser,它必须是 userList 之外的用户
所以我想要实现的是:我想要像List.getNext这样的东西,它接受 userList 和当前用户并返回列表中相对于 currentUser 的下一个用户
这是我的实现。我认为这非常复杂 - 那么有人知道如何以更好的方式做到这一点吗?
traverseList : List a -> a -> Maybe (Maybe a)
traverseList list currentElement =
let
indexList =
List.indexedMap
(\index element ->
if element == currentElement then
index
else
-1
)
list
currentAsIndex =
let
mayBeIndex =
List.maximum indexList
in
case mayBeIndex of
Just index ->
index
Nothing ->
0
getWanted =
List.map
(\( id, element ) ->
if id == (currentAsIndex + 1) then
Just element
else
Nothing
)
(List.indexedMap (,) list)
|> List.filter
(\element ->
element /= Nothing
)
|> List.head
in
getWanted
Run Code Online (Sandbox Code Playgroud)
解释:
我的方法是获取列表,创建给定列表的索引列表(看起来像这样 [-1, -1, -1, 3, -1, -1])
然后我得到这个列表的最大值 - 因为这给了我当前用户在 List.indexedMap 中的位置。
然后我将原始元素作为 List.indexedMap 进行迭代,并找出下一个元素(在我们的例子中为 4 号)并返回该元素。否则我什么也不返回。
然后,我过滤此“无内容列表”和仅一个用户,并使用 List.head 从列表中提取该用户。
结果是一个也许(也许用户)...这不太好...或者?
感谢您提供任何以更好的功能方式做类似事情的想法。
我真的很努力在函数式编程方面做得更好。
这是一个非常简单的递归解决方案:
getWanted : List a -> a -> Maybe a
getWanted list currentElement =
let findNextInList l = case l of
[] -> Nothing
x :: [] -> if x == currentElement
then List.head list
else Nothing
x :: y :: rest -> if x == currentElement
then Just y
else findNextInList (y :: rest)
in
findNextInList list
Run Code Online (Sandbox Code Playgroud)
这里的想法是查看列表的前两个元素,如果第一个是当前元素,则获取第二个。如果没有,请使用列表的尾部重试。
必须处理极端情况(您可以为此函数编写至少 4 个单元测试):
也许有一个更优雅的解决方案,但递归是函数式编程中非常常见的技术,所以我想分享这种方法。