我有積極的評分列表的數組:地圖排名在積極分數
[98.5, 85, 50, 50, 23, 0, 0, 0]
我想行列分配給這些分數:
[1, 2, 3, 3, 4, 5, 5, 5]
當兩個連續的得分有相同的價值,他們得到相同的排名。 任何想法如何以功能的方式解決這個問題?
(張貼在Haskell和紅寶石,因爲我認爲這兩種解決方案是可行的,可以移植)
我有積極的評分列表的數組:地圖排名在積極分數
[98.5, 85, 50, 50, 23, 0, 0, 0]
我想行列分配給這些分數:
[1, 2, 3, 3, 4, 5, 5, 5]
當兩個連續的得分有相同的價值,他們得到相同的排名。 任何想法如何以功能的方式解決這個問題?
(張貼在Haskell和紅寶石,因爲我認爲這兩種解決方案是可行的,可以移植)
在Ruby:
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]
哈斯克爾:
{-# 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
< =>uniq
和elemIndex
< =>index
。
不斷所以,稍微比@sawa不同:
a = [98.5, 85, 50, 50, 23, 0, 0, 0]
a.sort! {|e1,e2| -e1<=>-e2} # Just in case not already sorted
h = Hash[a.uniq.each_with_index.to_a]
a.map {|e| h[e]+1}
# => [1, 2, 3, 3, 4, 5, 5, 5]
編輯。我最初建議:
h = Hash[a.uniq.zip(1..a.size)]
a.map {|e| h[e]}
如果他們已經排序, 遞歸
eqNext (x:[email protected](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)
我們是否假設分數已經排序?
這裏是如何解決這個問題,如果他們不能假設排序:
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]
首先,將反向索引每個分數。然後按元組的第二個投影按降序排列。按照第二個投影進行分組會給出我們必須具有相同排名的分數列表。用等級列表進行壓縮將等級1賦予最大的等級。通過使用函數f
,我們同時放棄實際分數,使元組成爲一對(等級,反向索引)。現在需要按倒序索引的降序對這些元組進行排序,並得到第一個投影 - 排名。
另一個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]
我也注意到,相關性。而「reverse」也是一樣的。 – sawa
@sawa我原本稍微懷疑OPs「將haskell移植到ruby中,反之亦然」,但似乎合理可行的哈哈。現在它變成了紅寶石和哈斯克爾之間的人氣比賽 – jozefg
我對哈斯克爾瞭解不多,但是我聽說它在數學上很漂亮。也許OP可能已經添加了lisp。 – sawa