确定时间跨度列表中的时间间隔(列表中没有涵盖范围)

时间:2011-03-10 14:28:42

标签: haskell

我有一个时间跨度列表(以整数元组的形式给出),例如:

timespans = [ (1200, 1210)
        , (1202, 1209)
        , (1505, 1900)
        , (1300, 1500)
        , (1400, 1430)
        ]   

我想找到一个优雅的Haskell解决方案来确定列表中的时间跨度未涵盖的时间间隔。

4 个答案:

答案 0 :(得分:4)

首先,我会按照他们的开始时间排序。然后,您可以非常轻松地合并重叠跨度。一旦你有了它,你可以通过成对地迭代合并的跨度来找到间隙(通过用它的尾部拉链)。差距将是从第一项的结束时间到第二项的开始时间的跨度。

在代码中,这将是这样的:

mergeSortedSpans [] = []
mergeSortedSpans ((from1, to1):(from2, to2):spans) | to1 >= from2 =
   mergeSortedSpans $ (from1, max to1 to2):spans
mergeSortedSpans (span:spans) = span : mergeSortedSpans spans

inPairs _ [] = []
inPairs f (x:xs) = zipWith f (x:xs) xs

gap (_, to1) (from2, _) = (to1, from2)

gaps = inPairs gap . mergeSortedSpans . sort

用法:

gaps timespans
-- [(100,500),(1210,1300),(1500,1505)]

答案 1 :(得分:3)

我的解决方案使用分而治之的方法来融合所有重叠的时间跨度,以获得非重叠时间跨度的排序列表:

module Test
where

type Time  = Int 
type Start = Time
type Stop  = Time
type Span  = (Start, Stop)

timespans :: [Span]
timespans = [ (1200, 1210)
            , (1202, 1209)
            , (1505, 1900)
            , (1300, 1500)
            , (1400, 1430)
            , (500,1200)
            , (20,100)
            ]   


flattentime :: [Span] -> [Span]
flattentime [] = []
flattentime [x] = [x]
flattentime (s:ss) = combine (flattentime [ times | times <- ss, (fst times) < (fst s) ]) s
                             (flattentime [ times | times <- ss, (fst times) >= (fst s) ])

combine [] s [] = [s]
combine [] s ss2 = melt s (head ss2) ++ tail ss2
combine ss1 s [] = firsts ss1 ++ melt (last ss1) s 
combine ss1 s ss2 =  (firsts ss1) ++ melt3 (last ss1) s (head ss2) ++ (tail ss2)
melt (x1,x2) (x3,x4) | x2 < x3 = [(x1,x2), (x3,x4)]
                     | x4 < x2 = [(x1,x2)]
                     | otherwise = [(x1,x4)]

melt3 (x1,x2) (x3,x4) (x5,x6)  = if (length ss >1) then (head ss):(melt y (x5,x6)) else melt y (x5,x6)
                       where ss = melt (x1,x2) (x3,x4)
                             y = last ss

firsts [x] = []
firsts [] = []
firsts (x:xs) = x:(firsts xs)

它不是那么干净和优雅,我希望它会......任何人都有一个更短的解决方案吗?

答案 2 :(得分:3)

优雅 - 你的意思是什么?

import Data.List
timespans = [ (1200, 1210)
        , (1202, 1209)
        , (1505, 1900)
        , (1300, 1500)
        , (1400, 1430)
        ]   

gaps xs0 = filter g $ zipWith f xs (tail xs) where
  xs = merge $ sort xs0
  f (_, t0) (t1, _) = (t0, t1)
  g (t0, t1) = t0 < t1
  merge [] = []
  merge ((t0, t1):(t2, t3):ys) | t2 < t1 = merge ((t0, max t1 t3) : ys)
  merge (y:ys) = y : merge ys

main = print (gaps timespans)

答案 3 :(得分:2)

谢谢sepp2k - 你的权利;你建议的方式更容易!在使用Haskell-Code:

flattentime :: [(Integer,Integer)] -> [(Integer,Integer)]
flattentime [] = []
flattentime [x] = [x]
flattentime ((x1,x2):(y1,y2):ts) | y2<x2 = (x1,x2):(flattentime ts)
                                 | y1<x2 = (x1,y2):(flattentime ts)
                                 | otherwise = (x1,x2) : (flattentime ((y1,y2):ts))

然后我只需要打电话:

> (flattentime.sort) timespans