2
\$\begingroup\$

I have some code that has three lists, and it then checks the index of the second list against the index of the first as long as the first list has six elements. The code will then append to the third list if part of a string matches in the index of the first list. If the string does not match, it will append a message. I am hoping to find a better, more Pythonic way of writing my algorithm. Here is my code:

L1 = ["first = 1st","second = 2nd","third = 3rd","fourth = 4th","sixth = 6th",
  "first = A","second = B","third = C","fifth = E","sixth = F",
  "second = W","third = X","fourth = Y","fifth = Z","sixth = AA","first = BB"]
L2 = ["first","second","third","fourth","fifth","sixth"]
L3 = []

#Used in case a list has less than six elements
if len(L1) % 6 != 0:
    L1.append("Missing_Data")

c = 0
for i in L1:
    cont = True
    while cont:
        if L2[c] in i:
            L3.append(i.split("= ")[-1])
            c += 1
            if c < len(L2):
                cont = False
            else:
                c = 0
                cont = False
        else:
            L3.append("Missing_Data")
            c += 1
            if c < len(L2):
                continue
            else:
                c = 0
                break

This code works for what I want it to do but I think its too long. Any help in making this code more Pythonic would be greatly appreciated. Thanks in advance.

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you show the output for the example and explain a bit more how it relates to the input? I'd prefer not having to read the code in order to try to understand what the task is that it's supposed to do. Not least because it wouldn't be the first time that people post actually wrong code, in which case we can't deduce the task from the code. \$\endgroup\$ – superb rain Sep 17 at 13:41
2
\$\begingroup\$

My review of your current code is easy to summarize: It's too darn complicated and makes my head hurt. But don't feel bad, because you're in great company. First attempts are often like that – even for people who have been doing this for a long time.

What, specifically, makes it hard to understand? Algorithmic complexity: nested loops and conditionals, breaks, managing list indexes, and so forth. Whenever you perceive that type of complexity, it often helps to consider whether a more powerful data structure would simplify the situation (I'm using "data structure" in a very broad sense). In the rewrite offered below, we will use a special iterable that allows us to peek at the next value without actually consuming it every time. That one change drastically simplifies the bookkeeping inside the main loop, and it also simplifies how we append the needed remainder of missing values after we exit the loop.

# This is a third party library that is worth knowing about.
from more_itertools import peekable

# Your data, aligned so we can see what is going on.
# When you ask a question, it's a good idea to help your helpers.
xs = [
    'first = 1st', 'second = 2nd', 'third = 3rd', 'fourth = 4th',              'sixth = 6th',
    'first = A',   'second = B',   'third = C',                   'fifth = E', 'sixth = F',
                   'second = W',   'third = X',   'fourth = Y',   'fifth = Z', 'sixth = AA',
    'first = BB',
]

ys = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']

# Python has a builtin concept for missing data. Use it if you can.
# If you cannot, define a constant.
MISSING = None

# The results we want.
# When you ask a question, it's a good idea to provide this.
EXPECTED = [
    '1st',     '2nd',     '3rd',     '4th',     MISSING,   '6th',
    'A',       'B',       'C',       MISSING,   'E',       'F',
    MISSING,   'W',       'X',       'Y',       'Z',       'AA',
    'BB',      MISSING,   MISSING,   MISSING,   MISSING,   MISSING
]

# We will use a peekable iterable for both the Xs and the Ys.
xit = peekable(xs)
yit = None
results = []

# Process all Xs to build the results.
# A Y is consumed each time, and we get a fresh Ys iterable as needed.
# We consume an X only when current X and Y agree.
while xit:
    yit = yit or peekable(ys)
    x = xit.peek()
    y = next(yit)
    val = next(xit).split('= ')[-1] if y in x else MISSING
    results.append(val)

# The results should always contain a full cycle of Ys.
results.extend(MISSING for _ in yit)

# Check.
print(results == EXPECTED)
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is wonderful @FMc! I'm going to do more research on more_itertools to learn more about it. Using your code would drop the original by 13 lines. Cheers! \$\endgroup\$ – Hellyeah Sep 17 at 19:00
1
\$\begingroup\$
if c < len(L2):
    continue
else:
    c = 0
    break

Since continue always happens at the end of a loop, you can reverse these conditions, to make it shorter.

if c >= len(L2):
    c = 0
    break

now you don't need else since anything else than the break condition will continue automatically.

Higher up where you set cont = False, you could use break instead as far as I can tell. That removes the need for cont altogether so you can just do while True:

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I tried this and it works! Thank you for the insight. \$\endgroup\$ – Hellyeah Sep 17 at 14:42
0
\$\begingroup\$

I'm mostly answering on SO so my answer might not be following PEP8 or other guidelines but I tried to make a version of your code that is easier to see what's going on, without ifs, breaks, continues and having a smaller line count:

length = len(L2)
missing = 'Missing_Data'
index = -1

for item in L1:
    key,value = item.split(' = ')
    current = L2.index(key)
    no_missing = (current-index)%length-1 # get number of missing elements
    L3 += [missing] * no_missing # append this many of the missing value
    L3.append(value) # append current value
    index = current
    
L3 += [missing] * (length-index-1) # fill rest of list with missing elements
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.