python合并未排序的列表

时间:2016-11-07 17:42:19

标签: python list merge

如何在保留时合并2个任意未排序列表ab 这两个清单的顺序?我不想丢弃重复或排序。 格式化空白只是为了让人类读者可视化:

a = ['a', 'b', 'c', 'X',       'Y',      '127'      ]
b = ['a', 'b',      'X', '44', 'Y', 'w', '127', 'X' ]

所需输出m

m = ['a', 'b', 'c', 'X', '44', 'Y', 'w', '127', 'X' ]

我应该更简洁地指定合并顺序。     匹配优先级列在a列表中:     尝试将列表a中的每个项目与b

中的项目进行匹配
So if  a = ['b',      'a', 'r', 'n']
and    b = ['b', 'r', 'a',      'n'],
merged m = ['b', 'r', 'a', 'r', 'n']

字典解决方案删除重复项(b[2]b[7]都是'X')。

这需要是程序化的;我正在查看数百万行数据。 difflib很有意思,可能是另一个问题,但我认为这对这个问题没有帮助。

我在Windows-7上使用Python 2.7.12

下面的代码解决了这个问题,但它并不像我想的那样干净简单。

def merge_lists(a, b):
    """ Merge 2 arbitrary unsorted lists a and b while preserving
    the order from both lists. Do not discard duplicates or sort."""

    ia = ib = 0
    m = []    
    if len(a) == 0:
        m = b
    elif len(b) == 0:
        m = a

    while ia < len(a) and ib < len(b):
        if a[ia] == b[ib]:
            m.append(a[ia])
            ia += 1
            ib += 1
        else:
            count = b[ib:].count(a[ia])
            if count == 0:
                m.append(a[ia])
                ia += 1
            else:
                k = b[ib:].index(a[ia])
                for i in range(ib, k+ib):
                    m.append(b[i])
                ib += k

        if ia >= len(a):
            for i in range(ib, len(b)):
                m.append(b[i])
        if ib >= len(b):
            for i in range(ia, len(a)):
                m.append(a[i])

    return m #--- END --- merge_lists()

2 个答案:

答案 0 :(得分:3)

您可以使用difflib,但您必须自己进行合并。这可能很棘手 - 并且使用计算机并不容易(考虑到必须在版本控制系统中手动合并冲突时)。但是,很多情况可以自动处理。

这里有一些代码可以帮助您入门 - 我不保证它适用于所有情况,所以如果您找到了改进,请随时告诉我,我会尝试编辑它们:

a = ['a', 'b', 'c', 'X',       'Y',      '127'      ]
b = ['a', 'b',      'X', '44', 'Y', 'w', '127', 'X' ]
import difflib
matches = difflib.SequenceMatcher(a=a, b=b).get_matching_blocks()

# Pointers to locations in the `a` and `b` lists to keep track of our progress.
ix_a = 0
ix_b = 0
c = []
for match in matches:
    # Add in missing elements from `a` -- Assume `a` comes first?
    if match.a > ix_a:
        c.extend(a[ix_a: match.a])
    # add in missing elements from `b`
    if match.b > ix_b:
        c.extend(b[ix_b: match.b])
    # add in common elements.
    part = a[match.a:match.a + match.size]
    c.extend(part)

    # update our pointers into the original sequences.
    ix_a = match.a + match.size
    ix_b = match.b + match.size

print(c)

显然,你有点依赖于difflib选择匹配数据中的运行的方式。例如@ZeroPiraeus指出的示例:('barn''bran' 1 会产生'brarn',但如果您反转输入的顺序'baran'

这里令人惊讶的是,这两个结果并不相同 - 事实上,如果你改变输入的顺序,期望它们有不同的排序是很自然的。但是,它可能令人惊讶它们具有完全不同的值(一个有两个'r'而另一个有两个'a'。)

1 我为了简洁起见将这些列表格式化为字符串。

答案 1 :(得分:1)

由于指定了问题,因此没有单一的正确结果。例如:

a = ['b',      'r', 'a', 'n']
b = ['b', 'a', 'r',      'n']
m = ['b', 'a', 'r', 'a', 'n']

a = ['b', 'r', 'a',      'n']
b = ['b',      'a', 'r', 'n']
m = ['b', 'r', 'a', 'r', 'n']