在Haskell中查找字符串中最短和最长的单词

时间:2012-02-06 08:40:36

标签: haskell

我试图找到给定字符串中最短和最长的单词。如果输入的字符串是“自来水移动电话”,那么最长的单词应该是电话,最短的单词将被点击。我已经写了以下功能。如何找到字符串的索引并找到最短和最长的单词?

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

2 个答案:

答案 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)

maximumBymaximum类似,但它将第一个参数作为应该用于比较两个项目的函数。 comparing是一个高阶函数,可用于转换a -> b类型的函数(其中b是可以比较的某种类型,例如Ord b => a -> b如果你是已经熟悉类型约束)到两个a之间的比较函数(即a -> a -> Ordering类型的函数)。

最短的单词可以以类似的方式找到。