2013-11-26 73 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:一個列表不能代表完全爲零或一個結果。另外,界面一致性也很有價值。 –