我试图找到给定字符串中最短和最长的单词。如果输入的字符串是“自来水移动电话”,那么最长的单词应该是电话,最短的单词将被点击。我已经写了以下功能。如何找到字符串的索引并找到最短和最长的单词?
---------Converting string into a list of strings and finding length of each word--------
stringConvert :: String -> [Int]
stringConvert x = map (length) (words x)
----------Find the longest word-----------
findLongestWord :: String -> Int
findLongestWord x = maximum(stringConvert x)
----------Find the shortest word-----------
findShortestWord :: String -> Int
findShortestWord x = minimum(stringConvert x)
答案 0 :(得分:3)
以不同的方式思考问题。
import Data.Function (on)
stringConvert :: String -> [(String, Int)]
stringConvert s = map (\word -> (word, length word)) (words s)
findLongestWord :: String -> String
findLongestWord s = fst $ maximumBy (compare `on` snd) (stringConvert s)
-- findShortestWord is similar
我假设你只关心索引,所以你可以用它来查找单词。相反,我带着它的长度来传播这个词。
如果你真的想知道索引,你会想要像
这样的东西stringConvert :: String -> [((Int, String), Int)]
stringConvert s = zipWith (\index word -> ((index, word), length word)) [0..] (words s)
findLongestWord
的类型将会有所不同,但其定义保持不变。
修改:此技巧称为“decorate-sort-undecorate” or “Schwartzian transform”,在其他语言中也很有用。
第二次编辑: Data.Function应该随你的编译器一起提供,但同时这里是on
的定义:
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*.) `on` f = \x y -> f x .*. f y
答案 1 :(得分:3)
由于您正在寻找某个单词,因此您的函数的签名应为
findLongestWord :: String -> String
findShortestWord :: String -> String
你实现的stringConvert
函数有正确的想法,但它有点问题,因为结果没有哪个字与哪个长度相关联的信息。将字符串拆分为长度计算中的单词列表可能更好,并且有一个名为comparing
的便捷函数实际上完全不需要stringConvert
函数。
import Data.List (maximumBy)
import Data.Ord (comparing)
findLongestWord :: String -> String
findLongestWord s = maximumBy (comparing length) (words s)
maximumBy
与maximum
类似,但它将第一个参数作为应该用于比较两个项目的函数。 comparing
是一个高阶函数,可用于转换a -> b
类型的函数(其中b
是可以比较的某种类型,例如Ord b => a -> b
如果你是已经熟悉类型约束)到两个a
之间的比较函数(即a -> a -> Ordering
类型的函数)。
最短的单词可以以类似的方式找到。