I have two strings given as arguments to a Haskell function.
我有两个字符串作为Haskell函数的参数。
s1
is smaller than s2
if s1
is shorter than s2
or if they have the same length and s1
is lexicographically smaller than s2
.
如果s1短于s2或者如果它们具有相同的长度并且s1在词典上小于s2,则s1小于s2。
How do I implement this in Haskell?
我如何在Haskell中实现它?
6 个解决方案
#1
I'd use something like the following:
我会使用以下内容:
smaller :: String -> String -> Bool
smaller s1 s2 | len1 /= len2 = (len1 < len2)
| otherwise = (s1 < s2)
where (len1, len2) = (length s1, length s2)
Here's a sample run, in Hugs:
这是Hugs中的示例运行:
Main> smaller "b" "aa" True Main> smaller "aa" "b" False Main> smaller "this" "that" False Main> smaller "that" "this" True
#2
The one-pass solution:
一次通过解决方案:
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
#3
Try this:
compare s1 s2
(This returns LT, EQ, or GT).
(这会返回LT,EQ或GT)。
#4
An shorter version of the mappend
version by Tom Lokhorst above:
Tom Lokhorst上面的mappend版本的缩短版本:
import Data.Monoid (mappend)
import Data.Ord (comparing)
compareStrings :: String -> String -> Ordering
compareStrings = comparing length `mappend` comparing id
Another way, taking advantage of the ordering of tuples:
另一种方式,利用元组的顺序:
import Data.Ord (comparing)
import Control.Arrow ((&&&))
compareStrings :: String -> String -> Ordering
compareStrings = comparing (length &&& id)
#5
String
is an instance of Ord
and therefore you can use all of those methods to lexicographically compare string. As Andrew said, that's essentially compare
but also the comparison operators, (<)
among others.
String是Ord的一个实例,因此您可以使用所有这些方法按字典顺序比较字符串。正如安德鲁所说,这基本上是比较,但也比较运算符,(<)等。
smaller :: Ord a => a -> a -> Bool
smaller a b = a < b
This works for all types implementing Ord
(and is really just a crude wrapper for (<)
), including String
.
这适用于实现Ord的所有类型(实际上只是(<)的粗略包装),包括String。
#6
The normal string compare only works on lexicographical ordering, not the length of strings.
普通字符串比较仅适用于字典顺序,而不适用于字符串的长度。
So you'd have to write your own function to also check for the length:
所以你必须编写自己的函数来检查长度:
smaller :: String -> String -> Bool
smaller s1 s2 | length s1 < length s2 = True
| length s1 > length s2 = False
| otherwise = s1 < s2
Or a bit more general:
或者更一般:
compareStrings :: String -> String -> Ordering
compareStrings s1 s2 | length s1 < length s2 = LT
| length s1 > length s2 = GT
| otherwise = compare s1 s2
Example:
ghci> compare "ab" "z"
LT
ghci> compareStrings "ab" "z"
GT
We were toying around with Monoids at university last week, and we came up with this lovely alternative Ord
instance:
上周我们在大学里玩弄Monoids,我们想出了这个可爱的替代Ord实例:
instance Ord a => Ord [a] where
compare = comparing length
`mappend` comparing head `mappend` comparing tail
But if you don't quite understand this, I suggest you stick with the first definition ;-)
但如果你不太明白这一点,我建议你坚持第一个定义;-)
#1
I'd use something like the following:
我会使用以下内容:
smaller :: String -> String -> Bool
smaller s1 s2 | len1 /= len2 = (len1 < len2)
| otherwise = (s1 < s2)
where (len1, len2) = (length s1, length s2)
Here's a sample run, in Hugs:
这是Hugs中的示例运行:
Main> smaller "b" "aa" True Main> smaller "aa" "b" False Main> smaller "this" "that" False Main> smaller "that" "this" True
#2
The one-pass solution:
一次通过解决方案:
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
#3
Try this:
compare s1 s2
(This returns LT, EQ, or GT).
(这会返回LT,EQ或GT)。
#4
An shorter version of the mappend
version by Tom Lokhorst above:
Tom Lokhorst上面的mappend版本的缩短版本:
import Data.Monoid (mappend)
import Data.Ord (comparing)
compareStrings :: String -> String -> Ordering
compareStrings = comparing length `mappend` comparing id
Another way, taking advantage of the ordering of tuples:
另一种方式,利用元组的顺序:
import Data.Ord (comparing)
import Control.Arrow ((&&&))
compareStrings :: String -> String -> Ordering
compareStrings = comparing (length &&& id)
#5
String
is an instance of Ord
and therefore you can use all of those methods to lexicographically compare string. As Andrew said, that's essentially compare
but also the comparison operators, (<)
among others.
String是Ord的一个实例,因此您可以使用所有这些方法按字典顺序比较字符串。正如安德鲁所说,这基本上是比较,但也比较运算符,(<)等。
smaller :: Ord a => a -> a -> Bool
smaller a b = a < b
This works for all types implementing Ord
(and is really just a crude wrapper for (<)
), including String
.
这适用于实现Ord的所有类型(实际上只是(<)的粗略包装),包括String。
#6
The normal string compare only works on lexicographical ordering, not the length of strings.
普通字符串比较仅适用于字典顺序,而不适用于字符串的长度。
So you'd have to write your own function to also check for the length:
所以你必须编写自己的函数来检查长度:
smaller :: String -> String -> Bool
smaller s1 s2 | length s1 < length s2 = True
| length s1 > length s2 = False
| otherwise = s1 < s2
Or a bit more general:
或者更一般:
compareStrings :: String -> String -> Ordering
compareStrings s1 s2 | length s1 < length s2 = LT
| length s1 > length s2 = GT
| otherwise = compare s1 s2
Example:
ghci> compare "ab" "z"
LT
ghci> compareStrings "ab" "z"
GT
We were toying around with Monoids at university last week, and we came up with this lovely alternative Ord
instance:
上周我们在大学里玩弄Monoids,我们想出了这个可爱的替代Ord实例:
instance Ord a => Ord [a] where
compare = comparing length
`mappend` comparing head `mappend` comparing tail
But if you don't quite understand this, I suggest you stick with the first definition ;-)
但如果你不太明白这一点,我建议你坚持第一个定义;-)