リストから指数の最大値を見つける Haskell に関数があります。
prob99 = maximum $ map (\xs -> (head xs)^(head (tail xs))) numbers
私が見つける必要があるのは、結果のリストでこの最大値の場所です。これについてどうすればいいですか?
編集:私はこのような解決策を見つけました:
n = [[519432,525806],[632382,518061]....
prob99b [a,b] = b* (log a)
answer = snd $ maximum (Zip (map prob99b n) [1..])
最大要素のインデックスを見つける方法は?すべてのインデックスを試し、それらが最大であるかどうかを確認してみませんか?
ghci> let maxIndex xs = head $ filter ((== maximum xs) . (xs !!)) [0..]
しかし、これは関数がすでに存在するもののように聞こえます。既存の関数を使用すると、私のコードはより読みやすく、保守しやすくなり、おそらくさらに効率的になります。
参考までに、Haskellの型シグネチャで検索できる Hoogle と質問することもできます(Willが提案したとおり):
$ hoogle "Ord a => [a] -> Int" | head
<Nothing relevant>
$ # hmm, so no function to give me the index of maximum outright,
$ # but how about finding a specific element, and I give it the maximum?
$ hoogle "a -> [a] -> Int" | head
Data.List elemIndex :: Eq a => a -> [a] -> Maybe Int
Data.List elemIndices :: Eq a => a -> [a] -> [Int]
import Data.List
elemIndex 'b' "abc" === Just 1
Haskell関数を見つけるための本当に良いツールは Hoogle です。特にタイプシグネチャで検索できます。
すべてを1つのパスで実行したい場合は、Data.List.mapAccumLをお勧めします。これまでに見つかった最大数のインデックスをアキュムレータとして渡します。
これはおそらく彼自身の答えに値するに値しませんが、私はまだコメントできません。とにかく、これが私がこれを書いた方法です:
import Data.List
import Data.Ord
maxIndex :: Ord a => [a] -> Int
maxIndex = fst . maximumBy (comparing snd) . Zip [0..]
Haskellで数値計算をしている場合、それをより簡単かつ効率的にするライブラリを調べたいと思うかもしれません。たとえば hmatrix には、効率的なmaxIndex
sのためのメソッドVector
があり、そのドキュメントは次のとおりです。 https://hackage.haskell.org/package /hmatrix-0.17.0.1/docs/Numeric-LinearAlgebra-Data.html#g:14
> maxIndex $ vector [1, 3, 2]
1
質問が最初に尋ねられたとき、メソッドの正確な名前は異なりましたが、ライブラリもその頃にありました。
私はハスキーの初心者なので、次のように考えます。
Zip [0..] xs
_。 (Haskellインデックスはゼロから始まることに注意してください。つまり、リストの先頭は_x !! 0
_です。)各タプルの2番目の要素に従って、この圧縮リスト[(0, x!!0), (1, x!!1), ..., (n, x!!n)]
の最大値を見つけたいと思います。私がHaskellをよく知っていることに基づいて、いくつかの代替案があります:
maximumBy (comparing snd)
を使用してMaxime 以下に記述 としてこれを書くことができます。maximumBy
が存在することを知りませんでしたが、このようなものを疑っていたため、使用する型シグネチャに基づいて Hoogle で検索できました。 2つのa
パラメータの比較関数を使用して、a
要素のリストからジェネリック型a
をタイプします(_a -> a -> Ordering
_)–完全にどちらかです[a] -> (a -> a -> Ordering) -> a
、またはより論理的な引数の順列。考えてみると、リストを最後から2番目の引数として指定する方が理にかなっています。これは、すぐにわかるように、より良いカレー化を可能にするためです 検索してみましょう _(a -> a -> Ordering) -> [a] -> a
_。_import Data.List (foldl1')
maxBySnd :: Ord a => [(Int, a)] -> (Int, a)
maxBySnd = foldl1 cmpBySnd
where
cmpBySnd (i, xi) (j, xj) = case xi `compare` xj of
LT -> (j, xj)
_ -> (i, xi)
_
_foldl1'
_は左からフォールディングを開始し(アキュムレータがフォールディング関数の左側にあることを意味します)、累積インデックスはxj
がxi
より大きい場合にのみ更新されるため、これは最初の最大値のインデックスを返します。 _Data.List
_をインポートすることに恨みがあり、1000項目の長いリストで機能しない場合は、Preludeの_foldl1
_で問題ありません。 _Data.Vector
_パッケージは同様のアプローチを使用し、「maxIndex
」 here および here を検索するだけです。
Ord
さえ知りません。その場合、cmpBySnd
は_ cmpBySnd (i, xi) (j, xj) = if xi < xj then j else i
_
この時点では、代数的データ型と高次関数の利点を見逃しているでしょう(知らない場合、これを実現するのはほとんど不可能です)。そのため、1)質問するのは良いことです。 2)次の読者に Learn You A Haskell For Great Good 、または Real World Haskell 、または this SO回答 、または このGitHubリポジトリ 。
(i, xi)
_タプルの最初の要素を取得する必要があります。できれば組み込み関数fst :: (a, b) -> a
または自家製の関数first (a,b) = a
を使用します。最終結果は次のとおりです。
_import Data.List (maximumBy)
import Data.Ord (comparing)
maxIndex :: Ord a => [a] -> Int
maxIndex = fst . maximumBy (comparing snd) . Zip [0..]
-- or
-- maxIndex = fst . maxBySnd . Zip [0..]
_