在Haskell中如何检查字符串是否小于另一个字符串?

时间:2023-01-04 22:50:12

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 ;-)

但如果你不太明白这一点,我建议你坚持第一个定义;-)