作为输入,我有这样的列表(项目数量可能会改变):
b = [0.1, 1, 5, 8, 0.4, 2, 0.3, 0.4, 1, 2, 2, 3, 4, 5, 0.1]
如果列表中的两个下一个项是int和float,则插入到列表字符串" X"之后就像那样:
[0.1, 1, 5, 8, 'X', 0.4, 2, 'X', 0.3, 0.4, 1, 2, 2, 3, 4, 5, 'X', 0.1]
这是我的代码,第一部分检查满足此条件的项目数量,第二部分添加' X'。
c = 0
for i in range(len(b)):
if type(b[i]) == float and type(b[i-1]) == int:
c += 1
st = 0
while st < c:
for i in range(len(b)):
if type(b[i]) == float and type(b[i-1]) == int:
b.insert(i, "X")
continue
st += 1
print b
问题是如何优化此代码?
这是一些解决方案,但在这里我基于b列表的长度正在改变 - 糟糕的解决方案。
while True:
for i in range(0, len(b)):
if type(b[i]) == float and type(b[i-1]) == int:
b.insert(i, "ok")
continue
break
print b
答案 0 :(得分:2)
您可以使用以下命令找到正确的插入索引:
indexes = [i for i, pair in enumerate(zip(b, b[1:])) if isinstance(pair[0], int) and isinstance(pair[1], float)]
zip()只是创建一对相邻值。
[(0.1, 1), (1, 5), (5, 8), (8, 0.4), (0.4, 2), (2, 0.3), (0.3, 0.4), (0.4, 1), (1, 2), (2, 2), (2, 3), (3, 4), (4, 5), (5, 0.1)]
枚举将跟踪索引处的索引和值。您可以使用该值将类型与isinstance进行比较,并仅保留与您的过滤器匹配的索引。
对于您的示例,这将返回[3, 5, 13]
。但是,您不能简单地按顺序插入这些位置,因为索引会发生变化。
所以,你可以:
[3, 6, 15]
>>> for i in indexes[::-1]:
... b.insert(i+1, 'ok')
...
>>> b
[0.1, 1, 5, 8, 'ok', 0.4, 2, 'ok', 0.3, 0.4, 1, 2, 2, 3, 4, 5, 'ok', 0.1]
答案 1 :(得分:1)
你可以使用generator function一次性完成,每次我们得到一个匹配时设置一个标志,所以我们只生成一次相同的对象:
b = [0.1, 1, 5, 8, 0.4, 2, 0.3, 0.4, 1, 2, 2, 3, 4, 5, 0.1]
def insert_x(lst):
# create iterator
it = iter(lst)
# set matched to False initial and prev to the first element.
prev, matched = next(it), False
# start loop from second element.
for ele in it:
if isinstance(prev, int) and isinstance(ele, float):
yield prev
yield "X"
yield ele
matched = True
elif not matched:
yield prev
else:
matched = False
prev = ele
演示:
In [10]: b = [0.1, 1, 5, 8, 0.4, 2, 0.3, 0.4, 1, 2, 2, 3, 4, 5, 0.1]
In [11]: b[:] = insert_x(b)
In [12]: b
Out[12]: [0.1, 1, 5, 8, 'X', 0.4, 2, 'X', 0.3, 0.4, 1, 2, 2, 3, 4, 5, 'X', 0.1]
进行插入是很昂贵的,有些时间:
In [12]: b
Out[12]: [0.1, 1, 5, 8, 'X', 0.4, 2, 'X', 0.3, 0.4, 1, 2, 2, 3, 4, 5, 'X', 0.1]
In [13]: from random import choice
In [14]: b = [choice(b) for _ in range(100000)]
In [15]: timeit list(insert_x(b))
10 loops, best of 3: 91.2 ms per loop
In [16]: %%timeit
....: indexes = [i for i, pair in enumerate(zip(b, b[1:])) if isinstance(pair[0], int) and isinstance(pair[1], float)]
....: c = b[:]
....: for i in indexes[::-1]:
....: c.insert(i+1, 'ok')
....:
1 loop, best of 3: 1.5 s per loop
In [17]: timeit b[:]
1000 loops, best of 3: 895 µs per loop
In [6]: indexes = [i for i, pair in enumerate(zip(b, b[1:])) if isinstance(pair[0], int) and isinstance(pair[1], float)]
In [7]: c = b[:]
In [8]: for i in indexes[::-1]:
...: c.insert(i+1, 'X')
...:
In [9]: c == list(insert_x(b)) # exact same result.
Out[9]: True
如果你拿走c = b[:]
的费用,它仍然会明显变慢。差不多1.5秒vs 91ms。