2011-01-16 11 views
19

私はこの問題を簡単な方法で解決するための機能的な考え方では、非常に長いリストのために働くことはできません。あなたのようなリストがある場合:リストの中で最も長い単語を見つけるには?

maximum $ map length ["one", "two", "three", "four", "five"] 

私は、文字列に戻るには、前のステートメントを変更する方法を:

["one", "two", "three", "four", "five"] 

を私は最も長い単語の長さはかなり単純であるものを伝えることができます?

+0

@マークByersの戻り最長の単語の最初の出現:これはあなたにいくつかの処理を保存することがあります。 –

答えて

37

/イディオム(だけでなくPythonやスキームなどの他の言語で動作する):

snd $ maximum $ map (\x -> (length x, x)) ["one", "two", "three", "four", "five"] 

しかし、元のペイロードはまた、ソート・キーの一部であるため、結果は常に最も長い単語の最初の発生ではありません(この場合は最長の単語が1つしかありません)

+6

'compare \' on \ 'length'は' comparison'が 'Data.Ord'からのものであるとき' 'length length''です。 – Peaker

+0

本当にエレガントです。ニースの解決策。 –

3

,およびsndが簡単な構成である。 1は何が、簡単な方法は飾るソート-undecorateパターン、すぐに使用maximumByでしょうがなかった場合、ところで

import Data.List (maximumBy) 
import Data.Function (on) 

maximumBy (compare `on` length) ["one", "two", "three", "four", "five"] 
12

:あなたはこのような式を書くことができますmaximumByoncompareを使用して

+3

'maximumBy'でも、これは便利です。 'maximumBy'関数は各比較時に最長の現在のトークンの長さを(または比較関数が使用されているかどうかによって)再計算しますが、decorate-sort-undecorateは長さを1回だけ計算します。このバージョンは、控えめなサイズの入力であっても、はるかに効率的です。もちろん、あなたが任意の長さのリストを使用しているなら、おそらくリストを使うべきではありません。 –

+0

@ジョンあなたがデータのストリーム上で単一のパスを実行している場合、任意の長さのリストは完全にうまくいきます。私は気づいていなかったし、ちょっと驚きました( 'maximum'を実装しています)。' max(By) 'の問題を指摘してくれてありがとうございます。 – sclv

+0

単にfoldl1 maxは間違いなくエレガントです) – hvr

8

この関数(またはライブラリ)はあまり知られていないようですが、実際には、Data.Ordというモジュールがあり、これには関数comparingがほとんど含まれています上の答えでData.Function.onを使うのと同じですが、コードはより熟語的になります。

g>import Data.Ord 
g>import Data.List 
g>let getLongestElement = maximumBy (comparing length) 
getLongestElement :: [[a]] -> [a] 
g>getLongestElement ["one", "two", "three", "four", "five"] 
"three" 

コードは実際に英語のように表示されます。 「長さを比較することで最大になる」

+0

他の人はそれに同意せず、「比較する」は馬鹿げた特別なケースだと思います。私は気にしない、自分自身だが、私は経験豊かな人がそれに不平を言うのを聞いた。 – dfeuer

1

length aを計算するには、リスト全体をトラバースする必要がありますa。この特定のユースケースでは、最長の単語だけを心配していますが、正確にはどれくらいの長さであるかは関係ありません。したがって、どれが最長かを判断するために各リストに必要なだけの関数を書くことができます。

module Main where 

main = putStrLn $ longestWordInList ["one", "two", "three", "four"] 

longestWordInList = go "" 
    where go result [] = result 
     go result (x:xs) = let result' = longestWord result x in 
           result' `seq` go result' xs 

longestWord a b = go a b a b 
    where go a _ _ [] = a 
     go _ b [] _ = b 
     go a b (_:as) (_:bs) = go a b as bs 
+0

'go 'にはそれほど多くの引数は必要ありません。別の名前を使用して、外側のスコープ内の名前を参照してください。 'longestWord a b = go a b '= a a ...'に行きます。 – dfeuer

0
foldl (\accmax xs -> if length accmax < length xs then xs else accmax) [] ["one", "two", "three", "four", "five"] 
関連する問題