Search code examples
pythonmap-function

set item at multiple indexes in a list


I am trying to find a way to use a list of indexes to set values at multiple places in a list (as is possible with numpy arrays).

I found that I can map __getitem__ and a list of indexes to return the values at those indexes:

# something like
a_list = ['a', 'b', 'c']
idxs = [0, 1]
get_map = map(a_list.__getitem__, idxs) 

print(list(get_map)) # yields ['a', 'b']

However, when applying this same line of thought to __setitem__, the setting fails. This probably has something to do with pass-by-reference vs pass-by-value, which I have never fully understood no matter how many times I've read about it.

Is there a way to do this?

b_list = ['a', 'b', 'c']
idxs = [0, 1]
put_map = map(b_list.__setitem__, idx, ['YAY', 'YAY'])

print(b_list) # yields ['YAY', 'YAY', 'c']

For my use case, I only want to set one value at multiple locations. Not multiple values at multiple locations.

EDIT: I know how to use list comprehension. I am trying to mimic numpy's capability to accept a list of indexes for both getting and setting items in an array, except for lists.


Solution

  • The difference between the get and set case is that in the get case you are interested in the result of map itself, but in the set case you want a side effect. Thus, you never consume the map generator and the instructions are never actually executed. Once you do, b_list gets changed as expected.

    >>> put_map = map(b_list.__setitem__, idxs, ['YAY', 'YAY']) 
    >>> b_list                                                                  
    ['a', 'b', 'c']
    >>> list(put_map)                                                           
    [None, None]
    >>> b_list                                                                 
    ['YAY', 'YAY', 'c']
    

    Having said that, the proper way for get would be a list comprehension and for set a simple for loop. That also has the advantage that you do not have to repeat the value to put in place n times.

    >>> for i in idxs: b_list[i] = "YAY"                                       
    >>> [b_list[i] for i in idxs]                                              
    ['YAY', 'YAY']