Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace None with incremental value excluding values from skip list

Tags:

python

I am trying to replace all None values in all sublists within a list to incremental numbers starting from 0 but excluding the numbers from the skip list. And there is one more requirement. If first element of a sublist matches to any other sublists' first element, then they all need to have the same value that replaces None in them if present. This is what I could try so far.

skip = [1,2]
a = [[1, None, 2], [3, 4, 5], [1, None, 7], [8, 9, 10],[11, None, 12]]
b = 0
d = {}
for i in range(len(a)):
    if a[i][1]==None:
        if b in skip:
            print("found b in skip")
            b = b + 1
        if a[i][1] in d.keys():
            a[i][1] = d[a[i][1]]
        else:
            a[i][1] = b
        d[a[i][0]] = b
        b = b + 1
print(d)
print(a)

Output:

found b in skip
{1: 2, 11: 3}
[[1, 0, 2], [3, 4, 5], [1, 2, 7], [8, 9, 10], [11, 3, 12]]

Expected output:

[[1, 0, 2], [3, 4, 5], [1, 0, 7], [8, 9, 10], [11, 3, 12]]
like image 947
npatel Avatar asked Sep 11 '25 22:09

npatel


1 Answers

You're looking up the wrong element in the cache in a couple places, and not skipping properly when the skip list contains consecutive elements. Here's the minimal fix with inline comments indicating changed lines:

skip = [1,2]
a = [[1, None, 2], [3, 4, 5], [1, None, 7], [8, 9, 10],[11, None, 12]]
b = 0
d = {}
for i in range(len(a)):
    if a[i][1]==None:
        while b in skip:          # Loop until skipped all elements in skip
            print("found b in skip")
            b = b + 1
        if a[i][0] in d.keys():   # Check for first, not second element
            a[i][1] = d[a[i][0]]  # Use first element, not second, for lookup
        else:
            a[i][1] = b
            d[a[i][0]] = b  # Indent so we only set cached value on cache miss
            b = b + 1       # Indent so we only increment b on new first element
print(d)
print(a)

Try it online!

And here's a more heavily modified version that is somewhat more Pythonic, using names, not indexing (when possible):

skip = {1,2}  # Use set instead of list; if skip is large, list membership check will be expensive, set will stay cheap
a = [[1, None, 2], [3, 4, 5], [1, None, 7], [8, 9, 10],[11, None, 12]]
b = 0
d = {}
for sublist in a:                      # Loop over values instead of indexing a over and over, C-style (slow and less readable)
    first, middle, _ = sublist         # Unpack to useful names (reducing risk of misindexing, and making more readable code)
                                       # Not unpacking in for loop itself because we need to reassign elements of sublist
    if middle is None:                 # Always use is/is not to compare to None
        while b in skip:
            b += 1                     # Use += to avoid repeating variable name
        if first in d:                 # No need for .keys(); "in d" has same effect as "in d.keys()" and avoids creating unnecessary keys view
            sublist[1] = d[first]      # Indexing needed for assignment to modify original list
        else:
            sublist[1] = d[first] = b  # Can populate cache and reassign middle value all at once
            b += 1
print(d)
print(a)

Try it online!

Either version gets the expected output from the question.

like image 82
ShadowRanger Avatar answered Sep 13 '25 12:09

ShadowRanger