我有两个字符串作为参数给一个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