5

私の宿題は、最初のタプルの2番目の要素が2番目のタプルの最初の要素と同じである場合に、リスト内の2つのタプルをグループ化することです。次に、最初のタプルが(a, b)で、2番目(b, c)のタプルがである場合、タプル(a, c)を結果リストに追加する必要があります。

1つのタプルを持つ要素と多くのタプルを持つ2番目のリストを取り、それぞれを比較する最初の関数を作成しました。

これは正しく機能します:

c1 = ("a","x")
d1 = [ ("x","b"), ("z","c"), ("x","b"), ("z","c")
     , ("x","b"), ("z","c"), ("x","b"), ("z","c") ]

getByOne c1 a1 = filter (/=[])
  [ if (fst  (last(take n a1))) == (snd c1)
    then [((fst c1),  (snd  (last(take n a1))))]
    else  [] | n <- [1..(length a1) ] ]

出力:

[ [("a","b")], [("a","b")], [("a","b")], [("a","b")] ]

しかし、問題は、if thenとelseステートメントが単純なタプルだけをスローできないことです。そのため、新しいリストを作成します。この「回避策」の最後に、リスト内のリストを取得しています。また、出力リストが大きい場合は、リスト内のリストが多くなります。

タプルまたは空のタプルのみを渡す方法はありますか、またはこれらのリストを何らかの方法でグループ化する必要がありますか?

4

2 に答える 2

9

を使用して結果を平坦化できます

concat :: [[a]] -> [a]

ところで、テストはその引数に制約を課さないため、filter (/=[])条件(/= [])はより慣用的に書かれています(すでにここにあるので、慣用句の問題です)。not . nullnullEq

さらに、last (take n a1)はifのn- 番目の要素です。その制限が課せられているため、より簡潔に次のように表現できます。a11 <= n <= length a1a1 !! (n-1)

次に、構造的に

getByOne c1 a1 = concat $ [something c1 (a1 !! i) | i <- [0 .. length a1 - 1]]

(インデックスを index by にシフトしましたi)、これはより明確で効率的に次のように表現されます

getByOne c1 a1 = concat $ map (something c1) a1

よりもリスト内包表記を好む場合はmap、次のように書くこともできます。

getByOne c1 a1 = concat [something c1 x | x <- a1]

あなたの場合、alist-comprehension ジェネレーターでパターンマッチする機能を使用すると、

getByOne (f,s) a1 = concat [ if a == s then [(f,b)] else [] | (a,b) <- a1]

これははるかに短く、読みやすくなっています。if condition then [element] else []andを使用する代わりにconcat、リスト内包表記で条件を使用するとさらに便利です。

getByOne (f,s) list = [(f,b) | (a,b) <- list, a == s]

これは短くて明確です。

于 2012-11-04T10:16:44.870 に答える
3
  1. [1..(length a1)]書くことができます[1 .. length a1]
  2. [ if (fst  (last(take n a1))) == (snd c1)
      then [((fst c1),  (snd  (last(take n a1))))]
      else  [] | n <- [1..(length a1) ] ]
    

    書くことができます

    [ if fst lastElement == snd c1
      then [(fst c1, snd lastElement)]
      else [] | n <- [1 .. length a1 ]
              , let lastElement = last (take n a1) ]
    
  3. 次に、リストのインデックスを使用してそれを調べる代わりに、リストを直接使用します。

    [ if x == snd c1
      then [(fst c1, y)]
      else [] | (x, y) <- a1 ]
    
  4. 次に、リストを使用して解の有無を表す代わりに、次を使用しますMaybe

    import Data.Maybe
    
    c1 = ("a","x")
    d1 = [ ("x","b"), ("z","c"), ("x","b"), ("z","c")
         , ("x","b"), ("z","c"), ("x","b"), ("z","c") ]
    
    getByOne c1 a1 = catMaybes
            [ if x == snd c1
              then Just (fst c1, y)
              else Nothing | (x, y) <- a1 ]
    
  5. さらに良いことに、ガードを使用して if then else を取り除きます。

    getByOne (a, b) a1 = [ (a, d) | (c, d) <- a1
                                  , b == c ]
    

または、フィルターを使用する場合は、最初に一致するタプルのリストをフィルター処理してから、マップで対応する結果を作成します。

getByOne (a, b) a1 = map (\(_, c) -> (a, c))
                     . filter (\(c, _) -> b == c)
                     $ a1

これは次のように単純化されます

getByOne (a, b) = map (\(_, c) -> (a, c))
                     . filter (\(c, _) -> b == c)
于 2012-11-04T10:24:40.480 に答える