3

我目前的解决方案指针是

  • 以太通过迭代器类产生新的组装内部列表
  • 或通过产生新组装的内部列表的迭代函数

还有另一种更好的方法来解决这个挑战吗?

编辑

@Glenn:很好的反对意见。我没有想到这一点,因为我遇到的列表没有按照我想象的方式排序。

@THC4k:感谢您的解决方案。我学会了chain.from_iterable

@Mike DeSimone:嗯,测试了你的解决方案,但出了点问题,也许我错过了一些东西,......

@Jamie 和 Odomontois:感谢您指出要更详细

我的目标

我正在锻造一个小算法,它将任务列表 - 对/元组:(开始,停止) - 转换为简化的任务列表,其中重叠的任务合并在一起。

一个例外:当一个事件与另一个事件完全重叠时,我的算法失败(s1 s2 e2 e1)

详细的:

  • 我有一个成对的列表'taskList'(经验教训 - 元组:)。
  • 每个元组由 2 个日期时间对象组成:任务的开始和结束。
  • 重要:'taskList'的年表,其中顺序由开始确定,因为任务可能重叠p
  • 'taskList' 包含几天,因此是日期时间对象

示例,只是时间的字符串表示形式以提高可读性

taskList = [(9:00,10:00),(9:30,11:00),(11:00,12:30),(13:30,14:00),(14:00,18:00)]

最终结果:

result = [(9:00,12:30), (13:30,18:00)]

现在我的想法是,当我以我质疑的方式重新排列“任务列表”时

taskListT1 = [(9:00,),(10:00,9:30),(11:00,11:00),(12:30,13:30),(14:00,14:00),(18:00,)]

现在我可以消除那些 a >= b 的元组 (a,b):

taskListT2 = [(9:00,),(12:30,13:30),(18:00,)]

并转换回来:

result = [(9:00,12:30), (13:30,18:00)]
4

6 回答 6

1

好吧,这是有产量的解决方案:

# transform forwards
def transform_pairs( lst ):
    it = iter(lst)
    a,last = next(it)
    yield [a]
    for a,b in it:
        yield last, a
        last = b
    yield [last]

将列表转换回来应该看起来非常相似,但我将把它留给读者。

这是另一个稍微复杂一点的,可以双向转换的。它产生元组,因为固定长度的列表是蹩脚的。

from itertools import chain

def transform( iterable, offset):
    it = chain.from_iterable(iterable) # turn it back to one long list.
    if offset:
        yield next(it), # the trailing `,` makes this a tuple.
    for item in it:
        try:
            x = next(it)
        except StopIteration: # there is no 2nd item left
            yield item,
        else:
             yield item, x # yield the pair

print list(transform(transform([[1,2],[3,4],[5,6],[7,8]], True), False))
于 2010-08-16T22:43:11.820 回答
1

寻求“另一种更好的方法”选项(甚至使 OP 的异常正确):

def compress_task_list(tasks):
    tasks = list(tasks)
    tasks.sort(key=lambda item: item[0]) # make sure list is in order by start time
    result = []
    first_start = tasks[0][0]
    final_stop = tasks[0][1]
    for start, stop in tasks[1:]:
        if start > final_stop:
            result.append((first_start, final_stop))
            first_start = start
            final_stop = stop
        elif stop > final_stop:
            final_stop = stop
    result.append((first_start, final_stop))
    return tuple(result)

if __name__ == '__main__':
    import unittest

    class Test_Compress_Task_List(unittest.TestCase):
        def test_01(self):
            "completely separate"
            initial = ((8.0, 9.5), (10.0, 12.0), (13.0, 15.5), (16.0, 17.0))
            expected = ((8.0, 9.5), (10.0, 12.0), (13.0, 15.5), (16.0, 17.0))
            self.assertEqual(compress_task_list(initial), expected)
        def test_02(self):
            "end equals start"
            initial = ((8.0, 9.5), (9.5, 12.0), (13.0, 15.5), (15.5, 17.0))
            expected = ((8.0, 12.0), (13.0, 17.0))
            self.assertEqual(compress_task_list(initial), expected)
        def test_03(self):
            "end equals start (with more empty times)"
            initial = ((8.0, 8.5), (8.5, 10.0), (10.25, 12.0), (12.5, 13.75), (13.75, 15.0), (15.25, 16.0), (16.0, 17.0))
            expected = ((8.0, 10.0), (10.25, 12.0), (12.5, 15.0), (15.25, 17.0))
            self.assertEqual(compress_task_list(initial), expected)
        def test_04(self):
            "out of order, cross-overs, and tasks completely inside other tasks"
            initial = ((8.0, 8.5), (8.0, 10.0), (10.25, 12.0), (10.0, 11.5), (13.0, 15.5), (14.0, 15.0), (16.0, 17.0))
            expected = ((8.0, 12.0), (13.0, 15.5), (16.0, 17.0))
            self.assertEqual(compress_task_list(initial), expected)

    unittest.main()

请记住,这是 Python,可读性很重要。;)

于 2011-08-01T20:17:52.123 回答
0

Do you mean:

pairs = [[1,2], [3,4], [5,6], [7,8]]
print pairs, '->',
transformed = ([[pairs[0][0]]]+
               [[a,b] for a,b in zip(
                   (second for first, second in pairs[:-1]),
                   (first for first, second in pairs[1:]))]+
               [[pairs[-1][-1]]]
               )
print transformed
""" Output:
[[1, 2], [3, 4], [5, 6], [7, 8]] -> [[1], [2, 3], [4, 5], [6, 7], [8]]
"""
于 2010-08-16T22:12:39.063 回答
0
l = [[1,2], [3,4], [5,6], [7,8]]
m = [([] if i==0 else [l[i-1][1]] )+([] if i==len(l) else [l[i][0]]) for i in xrange(len(l)+1)]
于 2010-08-16T19:54:06.677 回答
0

这行得通,但感觉那里更像是 Pythonic:

l = [[1,2], [3,4], [5,6], [7,8]]
o = []
last = []
for a, b in l:
    o.append(last+[a])
    last = [b]
o.append(last)

print o

印刷

[[1], [2, 3], [4, 5], [6, 7], [8]]

这个机构也有效:

o = [[l[0][0]]]
for i in range(len(l)-1):
    o.append([l[i][1], l[i+1][0]])
o.append([l[-1][1]])
于 2010-08-16T19:40:07.840 回答
0

这是一个可以与生成器或列表输入一起使用的生成器,因此您不必将所有内容都保存在内存中:

def shift_pairs(inPairs):
    lastPair = None
    for pair in inPairs:
        if lastPair:
            yield [lastPair[1], pair[0]]
        else:
            yield [pair[0]]
        lastPair = pair
    yield [lastPair[1]]

我必须指出,在 Python 中,固定长度的短列表通常以元组的形式完成:

def shift_pairs(inPairs):
    lastPair = None
    for pair in inPairs:
        if lastPair:
            yield (lastPair[1], pair[0])
        else:
            yield (pair[0],)
        lastPair = pair
    yield (lastPair[1],)
于 2010-08-16T22:28:44.137 回答