Fast Efficient way to transfer an object to another list

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Apr 30 23:35:49 EDT 2010


On Fri, 30 Apr 2010 19:16:04 -0700, Jimbo wrote:

> Hello I have a relatively simple thing to do; move an object from one to
> list into another. But I think my solution maybe inefficient & slow. Is
> there a faster better way to move my stock object from one list to
> another? (IE, without having to use a dictionary instead of a list or is
> that my only solution?)


If you already know which object needs to be moved, it is easy: 


>>> fruits = ["apple", "banana", "carrot", "orange", "pear"]
>>> vegetables = ["potato", "lettuce", "onion"]
>>>
>>> # move carrot from fruits to vegetables
...
>>> vegetables.append("carrot")
>>> fruits.remove("carrot")
>>>
>>> print fruits
['apple', 'banana', 'orange', 'pear']
>>> print vegetables
['potato', 'lettuce', 'onion', 'carrot']


The only tricky thing is if you don't know which object needs to be 
moved. The way to solve that depends on what you need to do -- is there 
only one object that might need to be moved, or could there be more than 
one? How do you recognise it? There are many solutions. Here's one:


>>> even_numbers = []
>>> odd_numbers = odd_numbers = [1, 9, 8, 6, 2, 7, 3, 0, 4, 5]
>>> for i in range(len(odd_numbers)-1, -1, -1):
...     n = odd_numbers[i]
...     if n % 2 == 0:  # even?
...             even_numbers.append(n)
...             del odd_numbers[i]
...
>>> even_numbers
[4, 0, 2, 6, 8]
>>> odd_numbers
[1, 9, 7, 3, 5]


Can you see why I iterated over the list backwards? Why didn't I just do 
this?

for i, n in enumerate(odd_numbers):
    if n % 2 == 0:  # even?
        even_numbers.append(n)
        del odd_numbers[i]



You can re-write this more efficiently by using Python built-ins. First 
you need to recognise what it is doing: first it searches for the item 
with the stock code, then it appends it to the new list, then it deletes 
it from the old list.

> def transfer_stock(stock_code, old_list, new_list):
>     """ Transfer a stock from one list to another """ 
>     # is there a more efficient & faster way to
>     index = 0
>     for stock in old_list:
>         temp_stock = stock
>         if temp_stock.code == stock_code:
>             new_list.append(temp_stock)
>             del old_list[index]
>         index += 1
>     return new_list

If you know there is one, and only one, item with that stock code:


def transfer_stock(stock_code, old_list, new_list):
    """ Transfer a stock from one list to another """ 
    i = old_list.index(stock_code)  # search
    new_list.append(old_list[i])  # copy
    del old_list[i]  # delete
    return new_list


However, this will fail to work correctly if you have more than one 
identical stock codes that all need to be moved, or if there are none. So 
here's a version that handles both cases:


def transfer_stock(stock_code, old_list, new_list):
    """ Transfer a stock from one list to another """ 
    while True:  # loop forever
        try:
            i = old_list.index(stock_code)
        except ValueError:
            # not found, so we're done
            break
        new_list.append(old_list[i])
        del old_list[i]
    return new_list



-- 
Steven



More information about the Python-list mailing list