对python列表的子集进行排序,使其具有与其他列表中相同的相对顺序

时间:2015-05-28 10:44:01

标签: python algorithm list python-2.7 sorting

所以有一个列表说b = [b1, b2, b3]我希望能够以{{1}中存在的所有a的方式对列表bi进行排序具有与a中相同的相对顺序 - 仅剩下b个元素的其余部分。所以

a

b当然可以是元组或任何其他有序结构。我想出了什么

a = [ b1, x, b3, y, b2] -> [ b1, x, b2, y, b3]
a = [ b1, x, b2, y, b3] -> no change
a = [ b1, x, y, b2]     -> no change
a = [ b3, x, b1, y, b2] -> [ b1, x, b2, y, b3]

笨拙且O(n ^ 2)

2 个答案:

答案 0 :(得分:6)

  • 首先使用来自b的项目创建字典,其中键是项目,值是其索引,我们将使用它来在a中对匹配的项目进行排序。

  • 现在过滤掉该词典中存在的a项目,dict提供O(1)查找。

  • 现在对此筛选项目列表进行排序并将其转换为迭代器。

  • 现在再次循环a并检查每个项目是否存在于dict中,然后从迭代器中获取其值,否则按原样使用它。

def solve(a, b):
    dct = {x: i for i, x in enumerate(b)}
    items_in_a = [x for x in a if x in dct]
    items_in_a.sort(key=dct.get)
    it = iter(items_in_a)
    return [next(it) if x in dct else x for x in a]
...
>>> b = ['b1', 'b2', 'b3']
>>> a = [ 'b1', 'x', 'b3', 'y', 'b2']
>>> solve(a, b)
['b1', 'x', 'b2', 'y', 'b3']
>>> a = [ 'b1', 'x', 'b2', 'y', 'b3']
>>> solve(a, b)
['b1', 'x', 'b2', 'y', 'b3']
>>> a = [ 'b1', 'x', 'y', 'b2']
>>> solve(a, b)
['b1', 'x', 'y', 'b2']
>>> a = [ 'b3', 'x', 'b1', 'y', 'b2']
>>> solve(a, b)
['b1', 'x', 'b2', 'y', 'b3']

总时间复杂度最高为(O(len(a)), O(len(b)), O(items_in_a_length log items_in_a_length)

答案 1 :(得分:0)

接受的答案回答了问题,但我的实际问题有点限制 - 即我希望尽可能将项目保持在a的相同位置。所以接受的答案(以及我原来的尝试)会:

b = [ A, E, B ]
a = [ A, B, C, D, E, Z] -> [ A, E, C, D, B, Z ]

我想"冒泡"无序项目使他们失去了尽可能少的祖先:[ A, B, C, D, E, Z ] -> [ A, C, D, E, B, Z ]。请注意,之前的E会丢失祖先的C和D,而现在只会根据需要丢失B.边缘测试:

def reorder(a, b):
    bb = b[:]
    b_in_a = [x for x in a if x in set(b)]
    w = dict((x, i) for i, x in enumerate(a))
    while b_in_a:
        for i, (ordered, current) in enumerate(zip(bb, b_in_a)):
            if ordered != current:
                for j, x in enumerate(b_in_a[i:]):
                    if x == ordered: break
                    to = w[ordered] + 1 + j
                    w = dict((x,i if i < to else i+1) for x,i in w.iteritems())
                    w[x] = to # bubble them up !
                b_in_a.remove(ordered)
                bb = bb[i + 1:]
                b_in_a = b_in_a[i:]
                break
        else:
            break
    aa = a[:]
    a.sort(key=w.__getitem__)
    print aa, '-', b, ' -> ', a

# ['A', 'B', 'C', 'D', 'E'] - ['A', 'E', 'B']  ->  ['A', 'C', 'D', 'E', 'B']
# ['A', 'B', 'C', 'D', 'E', 'F'] - ['A', 'E', 'C', 'B']  ->  ['A', 'D', 'E', 'C', 'B', 'F']