我有兩個字符串作爲參數給一個Haskell函數。如何在Haskell中檢查字符串是否比另一個小?
s1
小於s2
如果s1
短於s2
或者如果它們具有相同的長度和s1
按字典順序比s2
小。
我該如何在Haskell中實現?
我有兩個字符串作爲參數給一個Haskell函數。如何在Haskell中檢查字符串是否比另一個小?
s1
小於s2
如果s1
短於s2
或者如果它們具有相同的長度和s1
按字典順序比s2
小。
我該如何在Haskell中實現?
我會使用類似以下內容:
smaller :: String -> String -> Bool
smaller s1 s2 | len1 /= len2 = (len1 < len2)
| otherwise = (s1 < s2)
where (len1, len2) = (length s1, length s2)
這裏有一個樣本來看,在擁抱:
Main> smaller "b" "aa" True Main> smaller "aa" "b" False Main> smaller "this" "that" False Main> smaller "that" "this" True
試試這個:
compare s1 s2
(這將返回LT,EQ或GT)。
String
是Ord
的一個實例,因此您可以使用所有這些方法按字典順序比較字符串。正如Andrew所說,這基本上是compare
,但也包括比較運算符(<)
等等。
smaller :: Ord a => a -> a -> Bool
smaller a b = a < b
這適用於各類實施Ord
(實際上只是爲(<)
粗包裝),包括String
。
我認爲OP希望較短的字符串比較長的字符串「小」,而不管它們的內容如何。例如,較小的「b」「aa」應該返回True。 (<)沒有考慮到長度,所以我不相信你的回答完全是OP要求的。 – 2009-05-04 12:13:39
正常字符串比較只適用於字典排序,而不適用於字符串的長度。
所以你必須編寫自己的功能,還需要檢查長度:
smaller :: String -> String -> Bool
smaller s1 s2 | length s1 < length s2 = True
| length s1 > length s2 = False
| otherwise = s1 < s2
或者多一點一般:
compareStrings :: String -> String -> Ordering
compareStrings s1 s2 | length s1 < length s2 = LT
| length s1 > length s2 = GT
| otherwise = compare s1 s2
例子:
ghci> compare "ab" "z"
LT
ghci> compareStrings "ab" "z"
GT
我們在Monoid附近玩耍上週的大學,我們想出了這個可愛的替代Ord
例如:
instance Ord a => Ord [a] where
compare = comparing length
`mappend` comparing head `mappend` comparing tail
但是,如果你不很明白這一點,我建議你堅持使用第一個定義;-)
比較長度的部分原因很有用,其他語言中的字符串的許多實現存儲或緩存字符串長度。好處是大多數字符串比較將花費時間O(1)作爲字符串長度的函數。 Haskell並非如此。作爲字符串長度的函數,所有與本機實現的字符串比較至少需要O(min(m,n))。 – yfeldblum 2009-05-04 11:35:30
當然,這甚至不是最快的實現可能。只是我認爲提問者要求提供比較版本,在字典順序之前首先檢查字符串的長度。如果您想打印字符串列表並認爲先打印較小的字符串會更漂亮,這可能很有用。 – 2009-05-04 11:44:07
@Tom:如果s2長於s1,我不確定您的小功能是否正常工作。例如,較小的「aa」「b」返回True。在我看來,OP希望函數在這種情況下返回False。 – 2009-05-04 12:09:02
該一個通溶液:
lengthcompare :: Ord a => [a] -> [a] -> Ordering
lengthcompare = lc EQ
where
lc lx [] [] = lx
lc _ [] _ = LT
lc _ _ [] = GT
lc EQ (v:vs) (w:ws) = lc (compare v w) vs ws
lc lx (_:vs) (_:ws) = lc lx vs ws
smaller :: Ord a => [a] -> [a] -> Bool
smaller s1 s2 = lengthcompare s1 s2 == LT
以上由湯姆Lokhorst一個較短的版本的mappend
版本:
import Data.Monoid (mappend)
import Data.Ord (comparing)
compareStrings :: String -> String -> Ordering
compareStrings = comparing length `mappend` comparing id
的另一種方式,以元組的排序的優點:
import Data.Ord (comparing)
import Control.Arrow ((&&&))
compareStrings :: String -> String -> Ordering
compareStrings = comparing (length &&& id)
我認爲OP希望較短的字符串比較長的字符串「小」,而不管它們的內容如何。比較「b」「aa」返回GT,但我認爲OP會希望在這種情況下返回LT的函數。 – 2009-05-04 12:19:02