views:

307

answers:

4

Say I have an array with a couple hundred elements. I need to iterate of the array and replace one or more items in the array with some other item. Which strategy is more efficient in python in terms of speed (I'm not worried about memory)?

For example: I have an array

 my_array = [1,2,3,4,5,6]

I want to replace the first 3 elements with one element with the value 123.

Option 1 (inline):

my_array = [1,2,3,4,5,6]
my_array.remove(0,3)
my_array.insert(0,123)

Option2 (new array creation):

my_array = [1,2,3,4,5,6]
my_array = my_array[3:]    
my_array.insert(0,123)

Both of the above will options will give a result of:

>>> [123,4,5,6]

Any comments would be appreciated. Especially if there is options I have missed.

+3  A: 
arr[0] = x

replaces the 0th element with x. You can also replace whole slices.

>>> arr = [1, 2, 3, 4, 5, 6]
>>> arr[0:3] = [8, 9, 99]
>>> arr
[8, 9, 99, 4, 5, 6]
>>>

And generally it's unclear what you're trying to achieve. Please provide more information or an example.


OK, as for your update. The remove method doesn't work (remove needs one argument). But the slicing I presented works for your case too:

>>> arr
[8, 9, 99, 4, 5, 6]
>>> arr[0:3] = [4]
>>> arr
[4, 4, 5, 6]

I would guess it's the fastest method, but do try it with timeit. According to my tests it's twice as fast as your "new array" approach.

Eli Bendersky
Thanks for the comments. I have updated my question. Hopefully it makes more sense now. I do like your method of replacing. The question is still what is more speed efficient?
Johan
Johan, did you try timing it with the timeit module?
Eli Bendersky
No I haven't. I don't know about the timeit module. I will go investigate it now :)
Johan
You should because you'll likely find that what intuitively should be faster isn't. And this is a bit tricky to measure properly.
Ned Deily
And, more importantly, unless you know this operation is going to be performed many, many times on lists orders of magnitudes bigger, any difference in speed or memory utilization will likely be unmeasurable in the overall program. Get the program to work correctly and then optimize if and where necessary.
Ned Deily
+6  A: 

If you want to replace an item or a set of items in a list, you should never use your first option. Removing and adding to a list in the middle is slow (reference). Your second option is also fairly inefficient, since you're doing two operations for a single replacement.

Instead, just do slice assignment, as eiben's answer instructs. This will be significantly faster and more efficient than either of your methods:

>>> my_array = [1,2,3,4,5,6]
>>> my_array[:3] = [123]
>>> my_array
[123, 4, 5, 6]
Daniel G
A: 

If you're looking speed efficience and manipulate series of integers, You should use the standard array module instead:

>>> import array
>>> my_array = array.array('i', [1,2,3,4,5,6])
>>> my_array = my_array[3:]
>>> my_array.insert(0,123)
>>> my_array
array('i', [123, 4, 5, 6])
juj
A: 

The key thing is to avoid moving large numbers of list items more than absolutely have to. Slice assignment, as far as i'm aware, still involves moving the items around the slice, which is bad news.

How do you recognise when you have a sequence of items which need to be replaced? I'll assume you have a function like:

def replacement(objects, startIndex):
    "returns a pair (numberOfObjectsToReplace, replacementObject), or None if the should be no replacement"

I'd then do:

def replaceAll(objects):
    src = 0
    dst = 0
    while (src < len(objects)):
     replacementInfo = replacement(objects, src)
     if (replacementInfo != None):
      numberOfObjectsToReplace, replacementObject = replacementInfo
     else:
      numberOfObjectsToReplace = 1
      replacementObject = objects[src]
     objects[dst] = replacementObject
     src = src + numberOfObjectsToReplace
     dst = dst + 1
    del objects[dst:]

This code still does a few more loads and stores than it absolutely has to, but not many.

Tom Anderson