我不知道如何给出准确的标题,但这就是问题所在。
问题:
我想给出一个排名列表(想象一些顶级列表),并且已经保留了一些位置。
假设我有7个插槽[1, 2, 3, 4, 5, 6, 7, 8]
,有些已经保留了位置1,3,4,7,9。(因为我们只有8个插槽,所以保留位置9将意味着最后一个插槽。)
然后我剩下2,5,6个插槽,我必须用其他物体填充它们。
简化问题:
我有两个清单:
>>> a = [1, 3, 4, 7, 9]
>>> b = [object_x, object_y, object_z]
我想将它们合并到这个:
>>> c = [1, object_x, 3, 4, object_y, object_z, 7, 9]
(我们可以将'object_x'设为0。)
就是这样,只是想看看是否有一种优雅的方式来实现它。
(根据评论编辑整个问题。非常感谢你们。)
答案 0 :(得分:2)
您可以使用生成器:
def merge(a, b):
b_clone = b[:]
for n in range(min(a), max(a) + 1):
if n in a:
yield n
elif b_clone:
yield b_clone.pop(0)
答案 1 :(得分:1)
我认为这涵盖了边缘情况,但我同意其他人认为必须有更好的方法来做到这一点。可能值得解释您尝试做的事情的背景。没有所有这些,可能有办法做到这一点。
def merge(a, b):
b = list(b)
a = iter(a)
current = 1
for item in a:
while item != current:
if b:
yield b.pop(0)
else:
yield item
yield from a # <3.3 use `for item in a: yield item` instead.
return
current += 1
yield item
current += 1
根据您的规范,它似乎正常工作:
>>> print(list(merge([1, 3, 4, 7, 9], [0, 0, 0])))
[1, 0, 3, 4, 0, 0, 7, 9]
>>> print(list(merge([2, 4, 5], [1, 3])))
[1, 2, 3, 4, 5]
还不清楚在b
中给出额外元素会发生什么 - 这会忽略它们,但在末尾添加yield from b
(或者,&lt; 3.3 for item in b: yield item
)会将它们作为最后的元素。
答案 2 :(得分:0)
这也应该有效:
>>>a = [2, 3, 5, 6, 7, 9]
>>>b = [0, 0, 0]
>>>length = len(a)
>>>i = 0
>>>while (i < length):
if a[i] != i+1:
a.insert(i, b.pop(0))
length += 1
i += 1
>>>print(a)
[0, 2, 3, 0, 5, 6, 7, 0, 9]
答案 3 :(得分:0)
谢谢大家,我得到了@jurgenreza启发的解决方案
>>> a = [1, 3, 4, 7, 9]
>>> b = [0, 0, 0]
>>> for i in a:
b.insert(i - 1, i)
>>> print b
[1, 0, 3, 4, 0, 0, 7, 9]
答案 4 :(得分:0)
你可能最好避免首先进行这种合并。如果您事先知道有多少可能的等级,则可以将列表开始包含多个None
,并且每次占用空格时,使用列表项分配而不是追加来设置。然后你的最终合并就像:
def merge(a, b):
b = iter(b)
for i,x in a:
if x is None:
a[i] = next(b)
如果你如此倾向,你可以将这个whoe数据结构放入一个类中,这样你也可以检查你何时尝试覆盖占用位置(如果这是一个错误):
class Ranks:
def __init__(self, size):
self._list = [None] * size
def __getitem__(self, position):
return self._list[position]
def __setitem__(self, position, val):
if self._list[position] is None:
raise ValueError('attempting to clobber existing rank data')
self._list[position] = val