在没有可能的情况下在Elm中转置 [英] Transpose in Elm without Maybe
问题描述
我有一个列表 [[1,2,3,4],[1,2,3,4]]
我想将它转置为 [[1,1],[2,2],[3,3] ...]
我有:
transpose:List(List a) - >列表(列表a)
转置ll =
((x :: xs):: xss) - > (x ::(List.map List.head xss))::转置(xs ::(List.map List.tail xss))
否则 - > []
但问题是编译器不喜欢头部和尾部操作,并且希望返回一个Maybe类型。
如何在elm中正确地转换列表?
这取决于...
您是否想要彻底地做到这一点,考虑所有的边缘案例?或者以快捷和肮脏的方式来做?我称之为边缘案例是列表的列表,其中子列表具有不同的长度。
非常脏的方式
在边缘情况下,您会遇到程序崩溃
unsafeHead l =
case $ of
(h :: t) - > h
_ - > Debug.crashunsafeHead用空列表调用
unsafeTail l =
case $ of
(h :: t) - > t
_ - > Debug.crashunsafeTail使用空列表调用
转置ll =
case b
((x :: xs):: xss) - >
让
头=
List.map unsafeHead xss
tails =
List.map unsafeTail xss
in
(x :: heads):: transpose(xs :: tails)
_ - >
[]
对于那些随机程序崩溃,祝你好运,不要说我没有' t警告你!
不关心边缘情况(或者:更短的行也可以)
在边缘情况下,您会得到: transpose [[10,11],[20],[],[30,31,32]] == [[10,20,30],[11, 31],[32]]
转置ll =
$ b [] - >
[]
([] :: xss) - >
转置xss
((x :: xs):: xss) - >
let
heads =
List.filterMap List.head xss
tails =
List.filterMap List.tail xss
in
(x :: heads):: transpose(xs :: tails)
拥抱可能
在边缘情况下,您会得到 Nothing
如果只有 $ c>可能 s通过与 List.head
/ List.tail
:
transpose:List(List a) - >可能(List(List a))
转置ll =
case b
((x :: xs):: xss) - >
让
头=
xss
|> List.map List.head
|>内部
尾巴=
xss
|> List.map List.tail
|>在
内
(x#^ heads)^#^((xs#^ tails)`Maybe.andThen`转置)
_ - >
if ll == List.filter List.isEmpty ll then
Just []
else
Nothing
-----一些辅助函数: -----
mCons:a - >也许(列表a) - >也许(列表a)
mCons v ml = Maybe.map((::) v)ml
v#^ ml = mCons v ml
- this真的是Maybe.map2(::) mv ml
- 但标准库不提供map2 :(
m2Cons:也许a - >也许(列表a) - >也许(列表a)
m2Cons mv ml =
case(mv,ml)of
(Just v,Just l) - > Just(v :: 1)
_ - > ; Nothing
mv ^#^ ml = m2Cons mv ml
- 刚刚列表的列表
insideout:List(也许a) - >也许(列出一个)
insideout l =
case l of
[] - > Just []
((Just v):: tail) - > v#^无尾巴
(Nothing :: _) - > Nothing
I have a list of lists of ints [[1,2,3,4],[1,2,3,4]]
I want to transpose that to [[1,1],[2,2],[3,3]...]
I have:
transpose : List (List a) -> List (List a)
transpose ll = case ll of
((x::xs)::xss) -> (x :: (List.map List.head xss)) :: transpose (xs :: (List.map List.tail xss))
otherwise -> []
but the issue is that the compiler doesn't like the head and tail operations and wants to return a Maybe type.
How do I transpose a list properly in elm?
It depends...
Do you want to do this thoroughly, considering all the edgecases? Or do it the quick and dirty way? What I'm calling an edge-case is a list of lists where the sublists have a different length.
Very dirty way
In edge-cases you get a program crash
unsafeHead l =
case l of
(h :: t) -> h
_ -> Debug.crash "unsafeHead called with empty list"
unsafeTail l =
case l of
(h :: t) -> t
_ -> Debug.crash "unsafeTail called with empty list"
transpose ll =
case ll of
((x::xs)::xss) ->
let
heads =
List.map unsafeHead xss
tails =
List.map unsafeTail xss
in
(x :: heads) :: transpose (xs :: tails)
_ ->
[]
Good luck with those random program crashes, don't say I didn't warn you!
Don't care about edge-cases (or: shorter rows are ok)
In edge-cases you get: transpose [[10,11],[20],[],[30,31,32]] == [[10,20,30],[11,31],[32]]
transpose ll =
case ll of
[] ->
[]
([] :: xss) ->
transpose xss
((x::xs) :: xss) ->
let
heads =
List.filterMap List.head xss
tails =
List.filterMap List.tail xss
in
(x :: heads) :: transpose (xs :: tails)
Embrace the Maybe
In edge-cases you get a Nothing
If you only want to transpose when you have a list of lists where all sublists are the same size, you can just hoist up the Maybe
s that you get from mapping with List.head
/List.tail
:
transpose : List (List a) -> Maybe (List (List a))
transpose ll =
case ll of
((x::xs)::xss) ->
let
heads =
xss
|> List.map List.head
|> insideout
tails =
xss
|> List.map List.tail
|> insideout
in
(x #^ heads) ^#^ ((xs #^ tails) `Maybe.andThen` transpose)
_ ->
if ll == List.filter List.isEmpty ll then
Just []
else
Nothing
----- Some helper functions: -----
mCons : a -> Maybe (List a) -> Maybe (List a)
mCons v ml = Maybe.map ((::) v) ml
v #^ ml = mCons v ml
-- this is really a Maybe.map2 (::) mv ml
-- but the standard library doesn't provide map2 :(
m2Cons : Maybe a -> Maybe (List a) -> Maybe (List a)
m2Cons mv ml =
case (mv,ml) of
(Just v, Just l) -> Just (v :: l)
_ -> Nothing
mv ^#^ ml = m2Cons mv ml
-- list of justs to just of list
insideout : List (Maybe a) -> Maybe (List a)
insideout l =
case l of
[] -> Just []
((Just v) :: tail) -> v #^ insideout tail
(Nothing :: _) -> Nothing
这篇关于在没有可能的情况下在Elm中转置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!