在没有可能的情况下在Elm中转置 [英] Transpose in Elm without Maybe

查看:93
本文介绍了在没有可能的情况下在Elm中转置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表 [[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 Maybes 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆