Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most elegant way to modify elements of nested lists in place

I have a 2D list that looks like this:

table = [['donkey', '2', '1', '0'], ['goat', '5', '3', '2']]

I want to change the last three elements to integers, but the code below feels very ugly:

for row in table:
    for i in range(len(row)-1):
        row[i+1] = int(row[i+1])

But I'd rather have something that looks like:

for row in table:
    for col in row[1:]:
        col = int(col)

I think there should be a way to write the code above, but the slice creates an iterator/new list that's separate from the original, so the references don't carry over.

Is there some way to get a more Pythonic solution?

like image 988
Conrad.Dean Avatar asked Apr 15 '11 04:04

Conrad.Dean


People also ask

How do I update a nested list in Python?

To add new values to the end of the nested list, use append() method. When you want to insert an item at a specific position in a nested list, use insert() method. You can merge one list into another by using extend() method.

What are nested lists give any example of nested list?

A nested list is a list that appears as an element in another list. In this list, the element with index 3 is a nested list. If we print( nested[3] ), we get [10, 20] .

What is the another name of nested list?

They're matrices (a list of rows, where each row is itself a list, or a list of columns where each column is itself a list). Lists are being used for what in other languages is known as structs, records, or tuples -- collections of data with a fixed structure.

What is a nested list how is it different from normal list?

Lists are useful data structures commonly used in Python programming. A nested list is a list of lists, or any list that has another list as an element (a sublist). They can be helpful if you want to create a matrix or need to store a sublist along with other data types.


4 Answers

for row in table:     row[1:] = [int(c) for c in row[1:]] 

Does above look more pythonic?

like image 181
Shekhar Avatar answered Sep 19 '22 22:09

Shekhar


Try:

>>> for row in table: ...     row[1:]=map(int,row[1:]) ...  >>> table [['donkey', 2, 1, 0], ['goat', 5, 3, 2]] 

AFAIK, assigning to a list slice forces the operation to be done in place instead of creating a new list.

like image 42
MAK Avatar answered Sep 19 '22 22:09

MAK


I like Shekhar answer a lot.

As a general rule, when writing Python code, if you find yourself writing for i in range(len(somelist)), you're doing it wrong:

  • try enumerate if you have a single list
  • try zip or itertools.izip if you have 2 or more lists you want to iterate on in parallel

In your case, the first column is different so you cannot elegantly use enumerate:

for row in table:
    for i, val in enumerate(row):
        if i == 0: continue
        row[i] = int(val)
like image 43
gurney alex Avatar answered Sep 20 '22 22:09

gurney alex


Your "ugly" code can be improved just by calling range with two arguments:

for row in table:
    for i in range(1, len(row)):
        row[i] = int(row[i])

This is probably the best you can do if you insist on changing the items in place without allocating new temporary lists (either by using a list comprehension, map, and/or slicing). See Is there an in-place equivalent to 'map' in python?

Although I don't recommend it, you can also make this code more general by introducing your own in-place map function:

def inplacemap(f, items, start=0, end=None):
    """Applies ``f`` to each item in the iterable ``items`` between the range
    ``start`` and ``end``."""
    # If end was not specified, make it the length of the iterable
    # We avoid setting end in the parameter list to force it to be evaluated on
    # each invocation
    if end is None:
        end = len(items)
    for i in range(start, end):
        items[i] = f(items[i])

for row in table:
    inplacemap(int, row, 1)

Personally, I find this less Pythonic. There is preferably only one obvious way to do it, and this isn't it.

like image 32
Wesley Avatar answered Sep 18 '22 22:09

Wesley