Haskell - 如果否则返回干净的元组

Bri*_*irs 5 haskell tuples list

我的作业任务是如果第一个元组的第二个元素与第二个元组的第一个元素相同,则将两个元组组合在一个列表中.然后,如果第一个元组是(a, b)第二个(b, c)元组,则(a, c)必须将元组添加到结果列表中.

我写了第一个函数,它带有一个元组的元素和带有许多元组的第二个列表,并将每个元组进行比较.

这个适当地工作:

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) ] ]
Run Code Online (Sandbox Code Playgroud)

输出:

[ [("a","b")], [("a","b")], [("a","b")], [("a","b")] ]
Run Code Online (Sandbox Code Playgroud)

但问题是,如果那时我不能抛出而其他声明只是简单的元组,所以我创建了一个新的列表.在这个"解决方法"的最后,我将获得列表中的列表,依此类推.此外,如果输出列表更大,列表中会有更多列表.

有没有办法只传递元组或空元组,或者我应该以某种方式分组这些列表?

Dan*_*her 9

您可以使用平坦化结果

concat :: [[a]] -> [a]
Run Code Online (Sandbox Code Playgroud)

然后你甚至不需要filter (/=[])- 顺便说一句,条件(/= [])更习惯性地写not . null,因为null测试不会Eq对其参数施加约束(你已经有一个约束,所以这只是成语问题).

此外,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]]
Run Code Online (Sandbox Code Playgroud)

(我已将指数转移到索引处i),这更清晰,更有效地表达为

getByOne c1 a1 = concat $ map (something c1) a1
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢列表理解map,您也可以将其写为

getByOne c1 a1 = concat [something c1 x | x <- a1]
Run Code Online (Sandbox Code Playgroud)

在你的情况下,使用alist-comprehension生成器中模式匹配的能力,给了我们

getByOne (f,s) a1 = concat [ if a == s then [(f,b)] else [] | (a,b) <- a1]
Run Code Online (Sandbox Code Playgroud)

这更短,更可读.而不是使用的if condition then [element] else []concat,甚至更好的是在列表理解使用条件,

getByOne (f,s) list = [(f,b) | (a,b) <- list, a == s]
Run Code Online (Sandbox Code Playgroud)

这简短明了.