python:[[1,2],[3,4],[5,6],[7,8]]转换为[[1],[2,3],[4,5],[6,7] ],[8]],反之亦然

时间:2010-08-16 19:33:12

标签: python list python-3.x swap

我目前的解决方案指针是

  • ether通过迭代器类生成新的汇编内部列表
  • 或通过iter函数生成新的汇编内部列表

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

修改

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

@ THC4k:谢谢你的解决方案。我学习了chain.from_iterable

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

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

我的目标

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

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

详细说明:

  • 我有一个带有对的列表'taskList'(课程 学到了 - 元组:)。
  • 每个元组 由2个datetimeobjects组成:start 并结束任务。
  • 重要的: 'taskList'的年代表 订单由start确定,因为 任务可能重叠
  • 'taskList'包含几天,因此是datetime对象

示例,只是字符串表示时间的可读性

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)]

现在我的想法是,当我以我质疑的方式重新排列'taskList'时

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)]

6 个答案:

答案 0 :(得分: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]

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

这是另一个可以在两个方向上转换的稍微复杂的一个。它会产生元组,因为固定长度的列表是 lame

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))

答案 1 :(得分: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,可读性很重要。 ;)

答案 2 :(得分: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]])

答案 3 :(得分: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)]

答案 4 :(得分:0)

你的意思是:

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]]
"""

答案 5 :(得分: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],)