Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在给定条件的情况下,增加前n个列表元素_Python_List_Python 2.7_List Comprehension - Fatal编程技术网

Python 在给定条件的情况下,增加前n个列表元素

Python 在给定条件的情况下,增加前n个列表元素,python,list,python-2.7,list-comprehension,Python,List,Python 2.7,List Comprehension,例如,我有一份清单 l = [10, 20, 30, 40, 50, 60] 我需要在给定条件的情况下增加列表的第一个n元素。该条件独立于列表。例如,如果n=3,则列表l应为: l = [11, 21, 31, 40, 50, 60] 我知道我可以在列表的每个元素上使用for循环来完成。但我需要做大约1.5亿次这样的手术。因此,我正在寻找一种更快的方法来实现这一点。非常感谢您的帮助。提前感谢您可以使用列表理解并添加剩余的列表 [x + 1 for x in a[:n]]+a[n:] 您可以

例如,我有一份清单

l = [10, 20, 30, 40, 50, 60]
我需要在给定条件的情况下增加列表的第一个
n
元素。该条件独立于列表。例如,如果
n=3
,则列表
l
应为:

l = [11, 21, 31, 40, 50, 60]

我知道我可以在列表的每个元素上使用
for
循环来完成。但我需要做大约1.5亿次这样的手术。因此,我正在寻找一种更快的方法来实现这一点。非常感谢您的帮助。提前感谢

您可以使用列表理解并添加剩余的列表

[x + 1 for x in a[:n]]+a[n:]

您可以在列表顶部创建一个简单的数据结构,其中存储每个增量操作的开始和结束范围。在您的情况下,起始值为0,因此您可以只存储结束值

通过这种方式,您不必实际遍历列表来增加元素,但只需保留在范围(例如{0到2}和{0到3})上执行的增量。此外,您还可以整理一些操作,这样,如果多个操作递增到同一个索引,您只需要存储一个条目

此解决方案的最坏情况复杂性是
O(q+g x qlogq+n)
其中g是get操作的数量,q是更新的数量,n是列表的长度。由于间隔最多可以有n个不同的结尾,这就减少到
O(q+nlogn+n)=O(q+nlogn)
。对每个查询使用更新的简单解决方案是
O(q*l
),其中l(查询的长度)可以达到n的大小,给出
O(q*n)
。因此,当
q>logn
时,我们可以预期此解决方案会更好

工作python示例如下:

def RangeStructure(object):

  def __init__(self, l):
    self.ranges = collections.defaultdict(int)
    self.l = l

  def incToPosition(self, k):
    self.ranges[k] += 1

  def get(self):
    res = self.l
    sorted_keys = sorted(self.ranges)
    last = len(sorted_keys) - 1                                                                                                                                                                                                                
    to_add = 0
    while last >= 0:
        start = 0 if last < 1 else sorted_keys[last - 1]
        end = sorted_keys[last]
        to_add += self.ranges[end]
        for i in range(start, end):
            res[i] += to_add
        last -= 1
    return res

rs = RangeStructure([10, 20, 30, 40, 50, 60])
rs.incToPosition(2)
rs.incToPosition(2)
rs.incToPosition(3)
rs.incToPosition(4)
print rs.get()

以下是NumPy中的操作聚合实现:

initial_array = # whatever your l is, but as a NumPy array
increments = numpy.zeros_like(initial_array)
...
# every time you want to increment the first n elements
if n:
    increments[n-1] += 1
...
# to apply the increments
initial_array += increments[::-1].cumsum()[::-1]

这是
O(ops+len(初始数组))
,其中
ops
是增量操作的数量。除非你只是在列表的一小部分上做少量的增量,否则这应该快得多。与naive实现不同,它不允许您在应用增量之前检索元素值;如果需要这样做,您可能需要基于BST或类似BST的结构的解决方案来跟踪增量。

m-查询计数,n-列表到增量长度,O(n+m)算法思想:
因为您只需要从开始到某个第k个元素递增,所以您将得到递增的范围。让我们的增量成对(到位置,增量为)。示例:
(1,2)-将位置0和1增加2
如果我们试图计算位置k处的值,那么我们应该将位置大于或等于k的增量添加到位置k处的当前值。如何快速计算位置大于或等于k的增量之和?我们可以从列表后面开始计算值,然后记住增量之和。
概念证明:

# list to increment
a = [1, 2, 5, 1, 6]
# (up to and including k-th index, increment by value)
queries = [(1, 2), (0, 10), (3, 11), (4, 3)]

# decribed algorithm implementation
increments = [0]*len(a)
for position, inc in queries:
    increments[position] += inc

got = list(a)
increments_sum = 0
for i in xrange(len(increments) -1, -1, -1):
    increments_sum += increments[i]
    got[i] += increments_sum


# verify that solution is correct using slow but correct algorithm
expected = list(a)
for position, inc in queries:
    for i in xrange(position + 1):
        expected[i] += inc

print 'Expected: ', expected
print 'Got:      ', got
输出:

Expected:  [27, 18, 19, 15, 9]
Got:       [27, 18, 19, 15, 9]

可能类似于
l[:n]=[x+1代表l[:n]]
。它可能和常规循环一样“慢”。如果循环是一个瓶颈,你确信Python是实现这一点的正确工具吗?你使用的是numpy吗?@dan man:它看起来像
my_list[:n]+=1
,Python中没有
++
,因此使用bool数组构建和索引将是不必要的开销。当你说“我需要做大约1.5亿次这样的手术。“-您是否有1.5亿个项目的列表要增加,或者您是否有一个短得多的列表需要部分增加,1.5亿次,或者150个短列表需要每个项目增加100万次?在某些情况下,每次递增的是同一个范围还是不同的范围?解释一下这比for循环快多少。为了获得更好的效率,您可能需要反向遍历递增位置,并跟踪需要向每个元素添加多少,而不是对超过它的每个范围端点将每个
res
条目增加一次。另外,您不需要调用
。按照现在的方式,如果您使用同一个参数多次调用
incToPosition
,则速度会更快。您能提供一个使用类似BST结构的解决方案吗?
Expected:  [27, 18, 19, 15, 9]
Got:       [27, 18, 19, 15, 9]