最有效的插入列表的方式

时间:2015-07-25 07:45:07

标签: python list list-manipulation

我正在阅读文件并构建列表a2。 我希望在前两个项目之后插入3行来列出a2列表中的b

b = ["This is a line", "another line", "and another one"]
a2 = ['a1', 'a2', 'a3']

i = 0
for x, y in map(None, a2[0:2], a2):
    i = i + 1
    if x == y:
        continue
    else:
        for newLine in b:
            a2.insert(i-1, newLine)
            i = i+1
print a2

以上确实给了我预期的结果,如['a1', 'a2', 'This is a line', 'another line', 'and another one', 'a3'],但由于我要用大文本文件构建列表并在其间插入几行,我想我必须让它更直观!

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

怎么样 -

df <- data.frame(column1=1)
df
#  column1
#1       1

演示 -

a2[2:2] = b

时间信息我所知道的一些方法(包括OP发布的方法) -

>>> b = ["This is a line", "another line", "and another one"]
>>> a2 = ['a1', 'a2', 'a3']
>>> a2[2:2] = b
>>> a2
['a1', 'a2', 'This is a line', 'another line', 'and another one', 'a3']

结果 -

def func1():
    b = ["This is a line", "another line", "and another one"]
    a2 = ['a1', 'a2', 'a3']
    i = 0
    for x, y in map(None, a2[0:2], a2):
        i = i + 1
        if x == y:
            continue
        else:
            for newLine in b:
                a2.insert(i-1, newLine)
                i = i+1
    return a2


def func2():
    b = ["This is a line", "another line", "and another one"]
    a2 = ['a1', 'a2', 'a3']
    a2 = a2[:2] + b + a2[2:]
    return a2

def func3():
    b = ["This is a line", "another line", "and another one"]
    a2 = ['a1', 'a2', 'a3']
    a2[2:2] = b
    return a2


import timeit

print timeit.timeit(func1,number=500000)
print timeit.timeit(func2,number=500000)
print timeit.timeit(func3,number=500000)

1.81288409233 0.621006011963 0.341125011444 有100000个元素且a有1000个元素的时间结果 -

b

结果 -

def func1():
    global a2
    global b
    i = 0
    for x, y in map(None, a2[0:2], a2):
        i = i + 1
        if x == y:
            continue
        else:
            for newLine in b:
                a2.insert(i-1, newLine)
                i = i+1
            break
    return a2


def func2():
    global a2
    global b
    a2 = a2[:2] + b + a2[2:]
    return a2

def func3():
    global a2
    global b
    a2[2:2] = b
    return a2

def func4():
    global a2
    global b
    a2.reverse()
    b.reverse()
    for i in b:
        a2.insert(-2, i)
    return a2

import timeit

a2 = ['a1' for _ in range(100000)]
b = ['a2' for i in range(1000)]

print timeit.timeit(func1,number=10,setup = 'from __main__ import a2,b')
print timeit.timeit(func2,number=10,setup = 'from __main__ import a2,b')
print timeit.timeit(func3,number=10,setup = 'from __main__ import a2,b')
print timeit.timeit(func4,number=10,setup = 'from __main__ import a2,b')

参考时间测试 - https://ideone.com/k4DANI

答案 1 :(得分:0)

我给出了这个答案,因为我们认为您的列表a2在开头并不是一个固定的大小,而是您要将list b的所有值插入{{ 1}} 之后 list a2

通常index 1以这种方式工作,如果list.insert()大小为list l1(想象这个n是hege),并且您尝试添加另一个巨大的n值从一开始就可以说从位置2 list l2开始,这应该将l1.insert(2, val)的所有其他元素从list l1移动到每个插入的下一个位置。

我们可以通过2 to n - 1reversing的{​​{1}}结尾来避免这种情况。

让我们考虑您的列表l1l2以及l1来自l2的所有insertl2 }。

l1

使用以下方式将index 2插入>>> l1 = range(1, 10) >>> l2 = range(10, 20) >>> l1 [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l2 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 后.......

l2

在上面插入每个插入的方式中,l1中的值>>> i = 2 >>> for j in l2: ... l1.insert(i, j) ... i += 1 >>> l1 [1, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5, 6, 7, 8, 9] 已经在适当的3, 4, 5, 6, 7, 8, 9后移动到下一个位置。假设你的&#39; l1&#39;大小为l1,这种价值变动成为开销。

为了避免每个插入内容在列表中移动数据,您可以从最后插入值,如果您要反转列表list.resizeten million并执行{{ 1}}

l1

插入后你会得到这个......

l2

如果您观察到以l1.insert(-2, l2.val)这种方式发生的数据移动,则在插入>>> l1 [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l2 [10, 11, 12, 13, 14, 15, 16, 17, 18, 19] >>> l1.reverse() >>> l2.reverse() >>> l1 [9, 8, 7, 6, 5, 4, 3, 2, 1] >>> l2 [19, 18, 17, 16, 15, 14, 13, 12, 11, 10] >>> for i in l2: ... l1.insert(-2, i) ... 的值时,只会移动值>>> l1 [9, 8, 7, 6, 5, 4, 3, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 2, 1]

您只需反转inserting即可获得所需的值列表。

2, 1

通过这种方式,我们可以避免l2中发生的最多l1

时间统计:https://ideone.com/owzWza

注意:整个解决方案在您的情况下运作良好,但如果您在>>> l1.reverse() >>> l1 [1, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5, 6, 7, 8, 9] 的{​​{1}}插入一些值,您可以再次考虑另一个最佳解决方案溶液

答案 2 :(得分:0)

如果你真的想做你在问题中所说的话。最快的解决方案(如果您插入的数组变大)将改为使用自定义容器类。已经指出反转列表会更快,但每次插入元素时反转列表(并在之后再次反转)也是昂贵的。像这样:

class ReverseList:
    def __init__(self, *args, **kwds):
        self.revlist = list(*args, **kwds)
        self.revlist.reverse()

    def __getitem__(self, key):
        # if you need slicing you need to improve this:
        return self.revlist[-key] 

    def __setitem__(self, key, val):
        # if you need slicing you need to improve this:
        return self.revlist[-key] = val

    def insert(self, pos, val):
        self.revlist.insert(-pos, val)

    # etc