【问题标题】:Nested lists , check if one list has common elements with other and if so join [duplicate]嵌套列表,检查一个列表是否与其他列表有共同元素,如果有,则加入 [重复]
【发布时间】:2015-03-05 20:19:13
【问题描述】:

我在列表中有一个列表说[[1, 3, 5], [2, 4], [1,7,9]]

我的要求是我想遍历列表并将其减少到

[[1,3,5,7,9], [2,4]].

我该怎么做??

【问题讨论】:

  • 减少它的标准是什么?奇偶?
  • 您究竟为什么要合并列表 1 和 3?仅仅因为他们共享元素1?
  • @tim 是的,如果他们有共同的元素我想合并他们
  • 你能不能举一个以上的例子!?
  • @DeadDjangoDjoker: 这个[[1,2], [3,4 ], [1,5,3], [5]] 会输出什么??

标签: python list python-2.7


【解决方案1】:

算法:

  1. 从新方法中获取基本元素。
  2. 从输入列表中删除第一项并为此创建新变量。
  3. 迭代新列表中的每一项。
  4. 通过 set intersection 方法检查 item 中的任何元素是否存在于基本集中。
  5. 如果存在则执行 6,7,8,9
  6. 通过 set update 方法使用当前项目更新基础。
  7. 从列表中删除当前项目。
  8. 将标志设置为True
  9. 打破for 循环,因为需要从第一项开始再次检查。
  10. 创建最终结果列表添加添加碱基和剩余列表。

[编辑:]

问题:

以前的代码将基础项目视为给定列表中的第一个项目,但是当此项目与其他项目没有匹配并且其他项目匹配时,代码将不起作用。

更新:

从给定列表中获取与列表中任何一项匹配的基本项。

[编辑2]:

将合并的项目插入到相应的位置

演示:

import copy

a = [[13, 15, 17], [66,77], [1, 2, 4], [1,7,9]]

#- Get base
base = None
length_a = len(a)
base_flag = True
i = -1
while base_flag and i!=length_a-1:
    i += 1
    item = a[i]
    for j in xrange(i+1, length_a):
        tmp = set(item).intersection(set(a[j]))
        if tmp:
            base = set(item)
            base_flag = False
            break

print "Selected base:", base
if base:
    tmp_list = copy.copy(a)
    target_index = i
    tmp_list.pop(target_index)
    flag = True
    while flag:
        flag = False
        for i, item in enumerate(tmp_list):
            tmp = base.intersection(set(item))
            if tmp:
                base.update(set(item))
                tmp_list.pop(i)
                flag = True
                break

    print "base:", base
    print "tmp_list:", tmp_list
    result = tmp_list
    result.insert(target_index, list(base))

else:
    result = a

print "\nFinal result:", result

输出:

$ python task4.py 
Selected base: set([1, 2, 4])
base: set([1, 2, 4, 7, 9])
tmp_list: [[13, 15, 17], [66, 77]]

Final result: [[13, 15, 17], [66, 77], [1, 2, 4, 7, 9]]

【讨论】:

  • 工作正常:)...谢谢:)
  • 请注意这是如何获得 4 个赞成票和一个接受(@DeadDjangoDjoker),这不起作用:ideone.com/PTMJvr。另请注意,大多数 set 方法(如交集、更新等)适用于任何可迭代对象,因此不需要转换为 set。
  • @AshwiniChaudhary:是的,正确的。我会在一段时间内更新。
  • @AshwiniChaudhary:现在检查。更新了,我知道是否需要更多改进,或者如果不适用于其他测试用例?
  • @DeadDjangoDjoker:根据 Ashwini 的评论,现在检查。
【解决方案2】:
a = [[1,2], [3,4 ], [1,5,3], [5]] # output: [set([1, 2, 3, 4, 5])]
# a = [[1, 3, 5], [2, 4], [1,7,9]] # output: [set([1, 3, 5, 7, 9]), set([2, 4])]

# convert them to sets
a = [set(x) for x in a]
go = True

while go:
    merged = False
    head = a[0]

    for idx, item in enumerate(a[1:]):
        if head.intersection(item):
            a[0] = head.union(item)
            a.pop(idx + 1)
            merged = True
            break

    if not merged:
        go = False

print a

【讨论】:

    【解决方案3】:

    这是相当低效的,但这可以解决问题:

    def combine_lists(lists):
        # Keep a set of processed items
        skip = set()
    
        for i, a in enumerate(lists):
            # If we already used this list, skip it
            if i in skip:
                continue
    
            for j, b in enumerate(lists[i + 1:], i + 1):
                # Use a set to check if there are common numbers
                if set(a) & set(b):
                    skip.add(j)
    
                    for x in b:
                        if x not in a:
                            a.append(x)
    
        # yield all lists that were not added to different lists
        for i, a in enumerate(lists):
            if i not in skip:
                yield a
    

    [edit]刚刚注意到顺序不再重要(您的输出表明它确实如此),这让事情变得更容易:)

    这个版本应该是相当理想的:

    def combine_lists(lists):
        # Keep a set of processed items
        skip = set()
        sets = map(set, lists)
    
        for i, a in enumerate(sets):
            # If we already returned this set, skip it
            if i in skip:
                continue
    
            for j, b in enumerate(sets[i + 1:], i + 1):
                # Use a set to check if there are common numbers
                if a & b:
                    skip.add(j)
                    a |= b
    
        # yield all sets that were not added to different sets
        for i, a in enumerate(sets):
            if i not in skip:
                yield a
    

    【讨论】:

    • 试过这个...dint 似乎对我有用:(...thanks aneways:)
    • 第一个解决方案似乎工作正常,但第二个不是:ideone.com/qFU86M
    • @AshwiniChaudhary: 哎呀...好像我在复制时出错了,最后一个lists 应该是sets。感谢您的提醒:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多