合并两个带有时间戳和队列长度的元组列表

时间:2015-07-24 11:27:47

标签: python merge

问题: 我有两个列表,其中包含需要合并的元组(每个由时间戳和队列长度组成):

L1 = [[0, 50], [7.75, 120], [10.25, 70], [17, 100], [20, 60]]

L2 = [[0, 80], [8, 120], [10, 85], [10.25, 80]]

我需要一个函数merge(L1,L2)返回:

[[ 0.00,  50+80 ],
 [ 7.75, 120+80 ],
 [ 8.00, 120+120],
 [10.00,  85+120],
 [10.25,  70+80 ],
 [17.00, 100+80 ],
 [20.00,  60+80 ]] # note

[注意:我不需要60+80 - 只是为了表明添加了哪些值60+80 = 140的结果是我需要的]

我从上面的输出中提取的是我反复的:

  • 从不同时间戳的合并列表(V的setwise union)中弹出最小值timestamps
  • 从非V时间戳列表中添加小于或等于V的队列长度。
  • ......直到V用尽。

我的问题: 我非常确定heapq可以解决它,但无法解决如何使用heapq-module构建解决方案。

更多漫无边际的细节:

  1. 在第一步中 - 在0.00和7.75之间,复合队列长度为50+80 - 取自L1[0][0] == L2[0][0]
  2. 我可以添加值L1[0][1]+L2[0][1] = 50+80。我现在使用了L1[0][:]L2[0][:]
  3. 在第二步 - 在7.75 - L2的队列没有增长,但L1的队列有:L1[1][0] = 120。因此,要获得复合队列长度,需要使用L1[1][1]添加L2[0][1]以获取120+80
  4. 我现在使用的第一个值大于以前记录的任何值,必须在接下来的步骤中使用,直到时间间隔用尽(23.99之后)。 "时间"中的下一个最大值是L2[1][0],即8.00。
  5. 当8.00大于7.75时,我需要合并这些值,以便在8.00时队列长度为120 + 120,基于L1的最大值小于8.00 - 即7.75。在此,我添加了L1 1和L2 1
  6. 在下一步中,最大的未使用值是来自L2的10.00。 L2的队列长度需要与L1最大值合并,小于或等于10.00 ......
  7. 所以它继续......

3 个答案:

答案 0 :(得分:4)

按事件顺序迭代事件,并保留上一次操作的时间戳(last_time),这样如果下一个事件具有相同的时间戳,但来自另一个队列,则两个更改将合并到result中的一个项目中。

def merge(a, b):
    l1 = [(t, value, 1) for (t, value) in a]
    l2 = [(t, value, 2) for (t, value) in b]
    events = l1 + l2
    events.sort()
    last_time = -1
    result = []
    c1 = 0
    c2 = 0
    for t, value, index in events:
        if index == 1: 
            c1 = value
        if index == 2: 
            c2 = value
        if t == last_time:
            result.pop()
        result.append((t, c1 + c2))
        last_time = t
    return result
In [26]: L1 = [[0, 50], [7.75, 120], [10.25, 70], [17, 100], [20, 60]]
         L2 = [[0, 80], [8, 120], [10, 85], [10.25, 80]]

         merge(L1, L2)

Out[26]: [(0, 130), (7.75, 200), (8, 240), (10, 205), (10.25, 150), (17, 180), (20, 140)]

答案 1 :(得分:1)

您也可以这样做:

def merge(z):
    previous=None
    l=[]
    z.sort()
    for i in range(len(z)):
        if i==len(z)-1:
            if previous==z[i][0]:
                continue
            else:
                l.append([float(z[i][0]),z[i][1])
        elif previous is None:
            previous=z[i][0]
            l.append([float(z[i][0]),z[i][1]+z[i+1][1]])
        else:
            if previous==z[i][0]:
                continue
            if z[i][0]<=z[i+1][0]:

                l.append([float(z[i][0]),z[i][1]+z[i-1][1]])
            else:
                l.append([float(z[i][0]),z[i][1]+z[i+1][1]])

    return l
L1 = [[0, 50], [7.75, 120], [10.25, 70], [17, 100], [20, 60]]
L2 = [[0, 80], [8, 120], [10, 85], [10.25, 80]]
z=L1+L2
print merge(z)

<强>输出:

[[0.0, 130], [7.75, 200], [8.0, 240], [10.0, 205], [10.25, 155], [10.25, 150], [17.0, 180], [20.0, 60]]

答案 2 :(得分:1)

受到galath's solution的启发,我试图找到两个以上输入的解决方案:

def merge(tup):
    events = list();
    i = 0 # ;-) Well, I wished I was able to compact this accumulation
    for l in tup:
        events += [(t, value, i) for (t, value) in l]
        i += 1
    events.sort(key=lambda x: x[0])
    result = dict()
    time = [0 for i in tup]
    for t, value, index in events:
        time[index] = value
        result[t] = sum(time)
    return sorted(result.items())

使用原始任务进行测试,

L1 = [[0, 50], [7.75, 120], [10.25, 70], [17, 100], [20, 60]]
L2 = [[0, 80], [8, 120], [10, 85], [10.25, 80]]
print merge([L1, L2])

输出是必需值,作为元组列表:

[(0, 130), (7.75, 200), (8, 240), (10, 205), (10.25, 150), (17, 180), (20, 140)]