weasel
weasel

Reputation: 574

Replacing every nth element in list of lists

I have a numerical list of list

a = [[1,2,3,4,5,6],
     [7,8,9,10,11,12],
     [13,14,15,16,17,18]]

and I want to replace every nth element with 0 to get something like this (n=3 in this case)

a = [[0,2,3,0,5,6],
     [0,8,9,0,11,12],
     [0,14,15,0,17,18]]

I am hoping to to it something like this

a = [[i, j if j %n == 0 else i] for i, j in a]

but I can't figure the arguments it needs.

Upvotes: 1

Views: 5076

Answers (6)

martineau
martineau

Reputation: 123423

Although it would take more than one line of code, you could create a generalized solution by doing it like shown below, which would modify the list-of-lists inplace and therefore be more efficient than recreating the whole thing just to change a few values.

def replace_nth(list_of_lists, n, value):
    for sublist in list_of_lists:
        for i, v in enumerate(sublist):
            if not i % n:
                sublist[i] = value

a = [[1,2,3,4,5,6],
     [7,8,9,10,11,12],
     [13,14,15,16,17,18]]

replace_nth(a, 3, 0)
print(a)  # -> [[0, 2, 3, 0, 5, 6], [0, 8, 9, 0, 11, 12], [0, 14, 15, 0, 17, 18]]

Upvotes: 1

Rishab P
Rishab P

Reputation: 1633

Solution

a = [[0 if index==0 else j for index, j in enumerate(i)] for i in a]

>>> a = [[1,2,3,4,5,6], [7,8,9,10,11,12], [13,14,15,16,17,18]]
>>> a = [[0 if index==0 else j for index, j in enumerate(i)] for i in a]
>>> a
[[0, 2, 3, 4, 5, 6], [0, 8, 9, 10, 11, 12], [0, 14, 15, 16, 17, 18]]

In Python 3.8 you will introduce Assignment Expressions.

It is a new symbol := that allows assignment in (among other things) comprehensions.

Upvotes: 0

Akshay Sehgal
Akshay Sehgal

Reputation: 19322

ggorlen has the right approach, but just to elaborate for your understanding and others who wanna learn list comprehensions..

First you need to iterate over each of the items in the list -

[item for item in l]

[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]]

Next, you have a condition that is applied on the index (position must be 3), but you need to modify the element itself as well. So you need to iterate over both the index and the element together.

[[(i,n) for i,n in enumerate(item)] for item in l]

[[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)],
 [(0, 7), (1, 8), (2, 9), (3, 10), (4, 11), (5, 12)],
 [(0, 13), (1, 14), (2, 15), (3, 16), (4, 17), (5, 18)]]

Each tuple is (index, element). Lastly you need your condition. There are multiple ways for using if conditions in a list comprehension, but for your case you need to check the index in the (index, element) tuple and see if it returns a remainder when divided by 3. If yes, then return the element else return 0.

[[n if i%3 else 0 for i,n in enumerate(item)] for item in l]

[[0, 2, 3, 0, 5, 6], [0, 8, 9, 0, 11, 12], [0, 14, 15, 0, 17, 18]]

Hope this explanation helps you with future problems like this.

Cheers.

Upvotes: 1

CIsForCookies
CIsForCookies

Reputation: 12817

What about slicing the list and creating a new one with 0?

n=3; a = [l[:n] + [0] + l[n+1:] for l in a]

Upvotes: 0

ggorlen
ggorlen

Reputation: 56875

You can use a ternary if-else inside the inner list comprehension and enumerate to access the index with each element as tuples:

n = 3
result = [[x if i % n else 0 for i, x in enumerate(y)] for y in a]

Applied to your example list,

>>> a = [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18]]
>>> n = 3
>>> [[x if i % n else 0 for i, x in enumerate(y)] for y in a]
[[0, 2, 3, 0, 5, 6], [0, 8, 9, 0, 11, 12], [0, 14, 15, 0, 17, 18]]

Upvotes: 5

Usman
Usman

Reputation: 2029

Try this code.

a = [[1,2,3,4,5,6],
 [7,8,9,10,11,12],
 [13,14,15,16,17,18]]

n=3
for out in range(0,len(a)):
    for i in range(0,len(a[out])):
        if i == n:
            a[out][i] = 0

print(a)

Upvotes: 0

Related Questions