代码之家  ›  专栏  ›  技术社区  ›  Jonno_FTW

在Haskell中查找列表中元素的索引?

  •  26
  • Jonno_FTW  · 技术社区  · 17 年前

    我有一个功能 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..])
    
    4 回复  |  直到 15 年前
        1
  •  39
  •   Alex Ling Zhong    7 年前

    如何找到最大元素的索引?试一试所有索引并检查它们是否为最大值如何?

    ghci> let maxIndex xs = head $ filter ((== maximum xs) . (xs !!)) [0..]
    

    仅供参考,你也可以问 Hoogle 可以搜索的 按Haskell类型签名(如建议):

    $ 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]
    
        2
  •  34
  •   Will    17 年前
    import Data.List
    elemIndex 'b' "abc" === Just 1
    

    Hoogle . 允许您按类型搜索签名和其他内容。

    如果您想一次完成所有操作,我建议使用Data.List.mapacuml,将迄今为止找到的最大数字的索引传递给累加器。

        3
  •  8
  •   Maxime Henrion    13 年前

    import Data.List
    import Data.Ord
    
    maxIndex ::  Ord a => [a] -> Int
    maxIndex = fst . maximumBy (comparing snd) . zip [0..]
    
        4
  •  1
  •   Daniel Landau    10 年前

    如果您在Haskell中进行数值计算,您可能希望查看使其更简单、更高效的库。例如 hmatrix 有办法 maxIndex 为了高效 Vector s、 文件如下: https://hackage.haskell.org/package/hmatrix-0.17.0.1/docs/Numeric-LinearAlgebra-Data.html#g:14

    > maxIndex $ vector [1, 3, 2]
    1
    

    最初提出这个问题时,方法的确切名称有所不同,但当时图书馆也在附近。

        5
  •  1
  •   Laszlo Treszkai    7 年前

    作为哈斯凯勒的新手,我会按照以下思路思考:

    1. zip [0..] xs . (请注意,Haskell索引从零开始,即列表的标题是 x !! 0 .)
    2. 我想找到这个压缩列表的最大值 [(0, x!!0), (1, x!!1), ..., (n, x!!n)] 根据每个元组的第二个元素。根据我对Haskell的了解程度,有几种选择:

      • 我可以把它写成马克西姆 wrote below ,使用 maximumBy (comparing snd) ,如果我知道这些函数存在的话。
      • 我不知道 maximumBy 存在,但我怀疑像这样的东西,所以我可以在上面搜索它 Hoogle a 从一系列 A. 元素,在两个元素上使用比较函数 A. 参数( a -> a -> Ordering )总的来说,两者都是 [a] -> (a -> a -> Ordering) -> a ,或更符合逻辑的参数排列。想一想,把这个列表作为倒数第二个论点更有意义,因为这样可以更好地进行咖喱,我们马上就会看到,所以 let's search for (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 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 answer 或 this GitHub repo .

    3. (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..]