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

发布于 2024-09-14 06:12:05 字数 1260 浏览 8 评论 0原文

我当前的解决方案指针将是

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

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

编辑

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

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

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

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

我的目标

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

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

详细信息:

  • 我有一个包含对的列表“taskList”(课程 学到了 - 元组:)。
  • 每个元组 由 2 个日期时间对象组成:开始 和任务结束。
  • 重要: “taskList”的时间顺序,其中 顺序由 start 决定,因为 任务可能会重叠
  • “任务列表”由几天组成,因此日期时间对象

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

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

时,我可以消除这些元组( ,b) 其中 a >= b:

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

并变换回来:

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

my current solution-pointers would be

  • ether via a iterator class which yields the new assembled inner lists
  • or via a iter function which yields the new assembled inner lists

is there another, better way to solve this challenge?

Edit

@Glenn: good objection.
I wasn't thinking of that because I experienced lists not ordered in the manner I thought.

@THC4k: thank you for your solution. I learned chain.from_iterable

@Mike DeSimone: Hmm tested your solution but something went wrong maybe I missed something yet,...

@Jamie and Odomontois:
Thank you for pointing out to be more detailed

my goal

I am forging a small algorithm which transforms a list of tasks – pairs/tuples: (start,stop) –
to a simplified list of task, where the overlapping tasks merged together.

One exeption: my algorithm fails when one event is completely overlapped by another (s1 s2 e2 e1 )

Detailed:

  • I've a list 'taskList' with pairs (lesson
    learned - tuples :).
  • each tuple
    consists of 2 datetimeobjects: start
    and end of a task.
  • important: the
    chronology of 'taskList' where the
    order is determined by start because
    tasks may overlapp
  • 'taskList' consists several days, therefore datetime objects

Example, just string representation of time for readability

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

final endresult :

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

now my thought was, when I rearrange the 'taskList' in the manner I questioned

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

now I can eliminate those tuples (a,b) where a >= b:

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

and transform back:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

落叶缤纷 2024-09-21 06:12:06

您的意思是:

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

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]]
"""
巡山小妖精 2024-09-21 06:12:06

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

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

This is a generator that can work with a generator or list input, so you don't have to keep everything in memory:

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

I must point out that, in Python, lists of short, fixed length are usually done as tuples:

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],)
空城缀染半城烟沙 2024-09-21 06:12:05

好吧,这里是yield:

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

Transforming the list back的解决方案应该看起来非常相似,但我将把它留给读者。

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

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

Well, here is the solutions with yield:

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

Transforming the list back should look very similar, but I'll leave that to the reader.

Here is another slightly more complicated one that can transform in both directions. It yield tuples because lists of fixed length are 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))
奶气 2024-09-21 06:12:05

选择“另一种更好的方法”选项(甚至使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,可读性很重要。 ;)

Going for the 'another, better way' option (even gets the OP's exception correct):

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

Remember, this is Python, and readability counts. ;)

葬シ愛 2024-09-21 06:12:05

这是可行的,但感觉就像有更多 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

prints

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

This works, but it feels like something more Pythonic is out there:

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

prints

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

This body also works:

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]])
衣神在巴黎 2024-09-21 06:12:05
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)]
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)]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文