5

私は肯定的なスコアのリストを持っています:

[98.5, 85, 50, 50, 23, 0, 0, 0]

これらのスコアにランクを割り当てたいと思います:

[1, 2, 3, 3, 4, 5, 5, 5]

連続する 2 つのスコアが同じ値の場合、それらは同じランクになります。これを機能的な方法で解決する方法はありますか?

( Haskell と Ruby で投稿されたのは、両方のソリューションが実行可能であり、移植できると思うためです)

4

6 に答える 6

12

ルビーの場合:

a = [98.5, 85, 50, 50, 23, 0, 0, 0]
sorted = a.sort.uniq.reverse
a.map{|e| sorted.index(e) + 1}
# => [1, 2, 3, 3, 4, 5, 5, 5]
于 2013-10-07T20:59:26.977 に答える
7

ハスケル:

{-# LANGUAGE TupleSections #-}
import Data.List
import Data.Maybe (mapMaybe)
import Data.Function (on)

rank, rank' :: [Double] -> [Int]

rank ls = mapMaybe (fmap (+1) . (`elemIndex` sorted)) ls
  where sorted = reverse . nub $ sort ls

-- Or Fixnum's faster solution
rank' = map fst . sortBy (compare `on` snd)
      . concat . zipWith (\n -> map (n,)) [1..]
      . groupBy ((==) `on` snd)
      . sortBy (flip compare `on` snd) . zip [1::Int ..]

興味深いことに、rankほとんど澤さんの答えです。nub<=>uniqelemIndex<=> index

于 2013-10-07T20:59:19.827 に答える
2

スコアがすでにソートされていると仮定しますか?

ソートされていると想定できない場合の解決方法は次のとおりです。

Prelude Data.List Data.Function> let f = (const .) . (,) :: a -> b -> c -> (a,b)
Prelude Data.List Data.Function> let sor s = sortBy ((flip compare) `on` snd) s
Prelude Data.List Data.Function> let rank scores = map fst . sor . concat . 
        zipWith (map . uncurry . f) [1..] . groupBy ((==) `on` snd) . 
        sor . zip [1,0..] $ scores
Prelude Data.List Data.Function> rank [11,13,13,12]
[3,1,1,2]

まず、各スコアに逆索引を付けます。次に、タプルの 2 番目の射影によって降順に並べ替えます。2 番目の射影でグループ化すると、同じランクでなければならないスコアのリストのリストが得られます。ランクのリストを圧縮すると、ランク 1 が最大数に割り当てられます。関数fを使用することで、実際のスコアを同時に破棄し、タプルを (ランク、逆インデックス) のペアにします。次に、これらのタプルを逆インデックスの降順で並べ替え、最初の射影であるランクを取得する必要があります。

于 2013-10-08T15:58:22.017 に答える
1

それらがすでにソートされている場合、 Recursive

eqNext (x:xs@(y:_)) acc = 
    let acc1 = if x == y then acc else acc + 1 in 
    acc1 : eqNext xs acc1
eqNext _ _ = []

els = 1 : eqNext ls 1

確認しよう:

> let ls = [98.5, 85, 50, 50, 23, 0, 0, 0]
> els
[1,2,3,3,4,5,5,5]

同じ非再帰的:

els = snd $ mapAccumL accF (0,0) ls
     where
      accF(ac,prev) b = let a1 = if ac == 0 || b /= prev then ac + 1 else ac in 
        ((a1,b), a1)
于 2013-10-07T21:48:29.843 に答える
1

別のRubyの答え:)

data = [98.5, 85, 50, 50, 23, 0, 0, 0, 85]
data.map{|value| data.select{|item| item > value }.size + 1 }

=> [1, 2, 4, 4, 6, 7, 7, 7, 2]

于 2015-08-17T08:18:28.133 に答える