2016-10-10 55 views
1

我有一個char和整數列表,如[('1',1),('2',2),('3',3),('4',4),('5',5)],並且希望將整數轉換爲總數中的每個數字的百分比,例如[('1',7),('2',13),('3',20),('4',27),('5',33)]。我嘗試了一個遞歸函數,它的參數爲(c,i):rest,然後將i除以總數,然後用rest調用該函數。但在每一次循環之後,總數都發生了變化。那麼是否有任何方法可以從頭開始聲明總體情況,並像其他語言一樣反覆使用它。Haskell - 遞歸函數中未修改的變量

回答

2

你需要預先計算總 - 您可以使用類似

f :: Integral b => [(a,b)] -> [(a,b)] 
f lst = let total = sum $ map snd list 
     in map (\(x,y) -> (x,(100 * y)`div` total)) lst 

注:這將是收集相關的事先每個字符Integral - 值是個好主意,這使得輸出有點更清楚(在我看來),但這將是一個聰明的讀者的練習。

爲了使這個功能更清晰 - 我也建議您推薦newtypes作爲ValuePercentage,這樣您就不會嘗試用百分比添加數值。

newtype Value a = V {extractV :: a} 
newtype Percentage = P {percent :: Integer} 

f :: Integral b => [(a,Value b)] -> [(a,Percentage)] 
+0

小挑剔:你不一定需要提前計算總數* - 你可以計算列表結果和輸入列表中的總數,這一切都歸功於懶惰的魔力。 – user2407038

+0

@ user2407038我並不完全理解這一點 - 如何在不計算之前計算的總和的情況下使用總和,並在單次遍歷中運行該總和。你的意思是百分比的計算被推遲到列表完全評估之後? – epsilonhalbe