我需要计算列表中值之间的值,即[135,136,138,140]将计算135-136,136-138,138-140之间的所有数字。输入列表[135.2,135.3,137,139]将使用[Float] [Float] [Int]类型输出[2,1,1]。到目前为止,我有:
heightbetween :: Float -> Float -> [Float] -> Int
heightbetween _ _ [] = 0
heightbetween n s (x:xs)
| (n < x) && (s > x) = 1 + (heightbetween n s xs)
| otherwise = heightbetween n s xs
count :: [Float] -> [Float] -> [Int]
count [] [] = []
count [x,y] = [(x,y)]
count (x:y:ys) = (x,y):count (y:ys)
forEach fun lst = heightbetween op ([],lst)
where
op (start,[]) = Nothing
op (start,a:as) = Just (start++(fun a):as
,(start++[a],as))
forPairs fun lst lst2 = map (map fst)
$ forEach (\(a,b)->(fun a b,b))
$ zip lst lst2
答案 0 :(得分:0)
你的count
看起来很奇怪。它应该是这样的:
-- count -> ranges -> data -> [counts]
count :: [Float] -> [Float] -> [Int]
count [] _ = [] -- no ranges given -> empty list
count [_] _ = [] -- no ranges, but single number -> empty list
count _ [] = [] -- no data given -> empty list
count (x:y:xs) d =
(heightbetween x y d) : count (y:xs) d
heightbetween :: Float -> Float -> [Float] -> Int
heightbetween _ _ [] = 0
heightbetween n s (x:xs)
| (n < x) && (s > x) = 1 + (heightbetween n s xs)
| otherwise = heightbetween n s xs
其他线路已过时。 然后调用
count [135,136,138,140] [135.2,135.3,137,139]
给出
[2,1,1]
答案 1 :(得分:0)
首先,确保您的范围列表有序......
rangePoints = [135,136,138,140]
orderedRangePoints = sort rangePoints
接下来,您会发现使用实际范围(您可以使用2元组(low,high)
表示)更容易
ranges = zip orderedRangePoints $ tail orderedRangePoints
你需要一个inRange函数(Data.Ix中已存在一个函数,但不幸的是它包含了upperbound,所以你不能使用它)
inRange (low,high) val | val >= low && val < high = True
inRange _ _ = False
您还需要订购输入点
theData = sort [135.2,135.3,137,139]
完成所有这些操作后,binCount函数很容易编写。
binCount'::[(Float, Float)]->[Float]->[Int]
binCount' [] [] = []
binCount' (range:rest) vals =
length valsInRange:binCount' rest valsAboveRange
where
(valsInRange, valsAboveRange) = span (`inRange` range) vals
注意,我定义了一个名为binCount'
的函数,而不是binCount
。我这样做了,因为我认为这是一个不安全的函数,因为它只适用于有序范围和值....你应该通过编写一个更安全的binCount
函数来完成它,它将所有上面的东西都放在它的位置条款。您应该添加所有类型和一些错误检查(如果值超出所有范围会发生什么?)。