Reputation: 961
Suppose I have a very huge array and I want to increment every element in the array by a given number. Is there a way to do this without iterating over all the elements?
I do not want to do the obvious iteration over all elements:
x = [ a + inc for a in x ]
Upvotes: 5
Views: 6480
Reputation: 364583
Oops, this is the same as Wolph's answer, but he only considers addition.
Keep track of all the scalar operations to be done to every array element, and do them on the fly as elements are accessed, or next time you do something non-scalar that touches every element.
You could implement a wrapper class that lets you add and multiply arrays by scalars, and just tracked the scalars to combine multiple operations into one. Code reading the array would go through a wrapper that did the mx+b operation.
Upvotes: 0
Reputation: 81644
One of the fastests ways I know is by using Numpy
:
from time import clock
li = range(500000)
start = clock()
li = [i+5 for i in li]
print "Time taken = %.5f" % (clock() - start)
>> Time taken = 0.06355
VS
from time import clock
import numpy as np
li = range(500000)
li = np.array(li)
start = clock()
li += 5
print "Time taken = %.5f" % (clock() - start)
>> Time taken = 0.00055
Note that I'm not timing the creation of the list itself and the creation of the Numpy
array.
Upvotes: 6
Reputation: 80031
No way to modify all numbers without looping over all of them. But you can wrap the collection with something that increments the number upon access.
>>> class OffsetCollection(object):
... def __init__(self, collection, offset):
... self.collection = collection
... self.offset = offset
... def __getitem__(self, key):
... return self.collection[key] + self.offset
...
>>> a = [1 ,3, 6, 7, 9, 0, 2]
>>> b = OffsetCollection(a, 5)
>>> a[3]
7
>>> b[3]
12
When using numpy it might do it with a lighter operation. Assuming you use 8 bits integer on a 64 bits number it would be possible to simply add the offset to every 8 bits of the 64 bits (so 8 numbers at a time) with 1 simple addition.
Upvotes: 2
Reputation: 10457
I am not sure if that is want you want, but.
There is constant time operation for this and is called generators so
y = ( a + inc for a in x )
And now y
is lazy generator. You can construct whole bunch of stuff this way in constant time.
What will take time, is "reconstructing" this back in list, but complexity can be reduced based on how many elements from beginning you take out.
Upvotes: -1
Reputation: 8492
There's no magic way to update every number in an array without ... updating every number in the array. You can phrase it differently if you really hate iterators for some reason:
x = map(lambda i: i + 1, x)
Upvotes: 0