所以有一个列表说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)
答案 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']