2013-11-26 44 views
0
tuplesList = [('a','m'), ('b', 'n'), ('c', 'o'), etc] 

如何通过先观察第一要素,并返回第二,如果发现搜索这个列表中的数值,但如果没有找到,那么看一下第二个元素,返回的第一个元素如果找到。例如搜索'a'会返回'm'并搜索'n'会返回'b'?双向搜索元组的列表

我尝试这样做:

lookup :: Char -> [(Char,Char)] -> Char 

lookup x zs = (head [b | (a,b) <- zs, (a==x)]) 

lookup x zs = (head [a | (a,b) <- zs, (b==x)]) 

,但我不知道怎么说,如果二号线没有找到匹配,则执行3号线。 任何帮助表示赞赏。

回答

1

哈斯克尔已经its own lookup function,你或许应该利用:

lookup' :: Char -> [(Char,Char)] -> Char 
lookup' x zs = case (search1, search2) of 
        (Just y, _)  -> y 
        (Nothing, Just y) -> y 
        (Nothing, Nothing) -> error "What am I supposed to do here I DON'T KNOW" 
where search1 = lookup x zs 
     search2 = lookup x [(b,a) | (a,b) <- zs] 
+2

'Alternative'从'Control.Applicative'将方便在这里:'查找” X ZS =查找X ZS <|>查找X(FMAP交换ZS )' –

+0

完美。有用。 – user2846043

1

一个很好的方式来扩大你的部分解决方案是考生的两份名单正好连接在一起,如:

lookup x zs = head ([ b | (a,b) <- zs, a == x ] ++ [ a | (a,b) <- zs, b == x ]) 

你明白这是为什么可行吗?


这不是最高效的,因为如果有元组的第一个组件上的不匹配它会经过两次zs - 如果zs是非常大的这种持有超过必要ZS更长。

为了提高我会做这样的事情(但只有当它是非常重要的!):

lookup x zs = goNoSecondBestYet zs where 
    goNoSecondBestYet [] = error "Nothing found" 
    goNoSecondBestYet ((a,b):abs) 
     | a == x = b -- we're done! 
     | b == x = goSecondBestFound b abs -- keep track of the newly found second best candidate 
     | otherwise = goNoSecondBestYet abs -- just go on 
    goSecondBestFound y [] = y 
    goSecondBestFound y ((a,b):abs) 
     | a == x = b -- we're done, never mind the second best 
     | otherwise = goSecondBestFound y abs -- keep going, we already have a second best 

这是非常复杂的已经(尝试推广这种使用4元组,看看有什么我的意思是!),我通常会使用Maybe这个;但它确实只通过列表一次。

0

您应该考虑查找可能会失败。自然的事情做的,是返回结果的列表:

lookup :: Eq a => a -> (a,a) -> [a] 
lookup item xs = [ if a==c then b else a | (a,b) <- xs, a == c || b == c ] 
+0

'lookup'通常返回一个Maybe。 –

+0

是的,@ReinHenrichs,我知道,但是列表至少**和Maybe一样好,并且由于我们有一个列表,所以在这里构造另一个类型根本不明智。只要你用listToMaybe或者其他的前缀来完成整个事情,并且一旦你修改了使用这个函数的所有事件,就会想出第二​​个匹配。或者最后一场比赛。 – Ingo

+0

一个列表至少不如一个Maybe:一个列表不能代表完全为零或一个结果。另外,界面一致性也很有价值。 –