Devin Liner
Devin Liner

Reputation: 449

filtering through a list using for loops and conditionals

Using Python 2.7. I have the following list inside of a list:

 channels = [[ch1a.twist, ch1b.twist, ch1c.twist, ch2a.bop, ch2b.bop, ch3c.pull]]
 new_list = []

I want to apply the following logic to my code:

I would like to run the for loop such that

channels = [...]
new_list = []
for "blah":
   do stuff

print new_list
>> new_list = [ch1a.twist, ch2a.bop, ch3c.pull]

So far I have

 for list in channels:
    for ch in list:
        try: 
            prefix, suffix = ch.split('.')
        except ValueError:
            pass 
        else:
            if 'a' in prefix:
                new_list.append(ch)
            elif 'b' in prefix:
                new_list.append(ch)

but this is still returning the ch1a.twist and the ch1b.twist...grrrrrr. I thought 'elif' was supposed to mimic the following logic: 'else if previous condition was not met then execute the following'

Upvotes: 0

Views: 54

Answers (2)

DatHydroGuy
DatHydroGuy

Reputation: 1116

I got the same error as @roganjosh, so I've assumed that your list-within-a-list should contain strings (it's a simple enough change if they're not).

The main issue with your provided code is that if you ever hit the code to check whether 'b' is in the prefix, then you are never looking to see whether you've already added the channel number to new_list.

The easiest way I've found to modify your code is as follows (it's not pretty, but I was trying to keep your code as un-touched as possible):

Firstly, sort the list-within-a-list using channels[0].sort()

Next, track which channel number you have already added by initialising a list using channelNumbers = []

Next, I split the prefix so that I separate the channel number from the channel version:

channelNumber = prefix[:-1] channelVersion = prefix[-1:]

Finally, I tweak your elif statements so that they only add the b- or c- versions if the channel number hasn't already been added: elif 'b' in prefix and not channelNumber in channelNumbers: and elif 'c' in prefix and not channelNumber in channelNumbers:

So the full code becomes:

channels = [['ch1a.twist', 'ch1b.twist', 'ch1c.twist', 'ch2a.bop', 'ch2b.bop', 'ch3c.pull']]
new_list = []
channelNumbers = []
channels[0].sort()

for list in channels:
    for ch in list:
        try:
            prefix, suffix = ch.split('.')
            channelNumber = prefix[:-1]
            channelVersion = prefix[-1:]
        except ValueError:
            pass
        else:
            if channelVersion == 'a':
                new_list.append(ch)
                channelNumbers.append(channelNumber)
            elif channelVersion == 'b' and not channelNumber in channelNumbers:
                new_list.append(ch)
            elif channelVersion == 'c' and not channelNumber in channelNumbers:
                new_list.append(ch)

print(new_list)

And the output is, as you requested: ['ch1a.twist', 'ch2a.bop', 'ch3c.pull']

Upvotes: 0

Kevin
Kevin

Reputation: 76194

Assuming:

  • you intended for ch1a.twist et al to be string literals, and just forgot the quote marks
  • channels contains exactly one list
  • All the versions of a channel are next to one another in the list
  • The versions are in alphabetical order (so, say, "ch1b" never comes before "ch1a")

Then you can use groupby to group the items by channel name, and extract the first occurrence of each channel using next.

import itertools
def channel_name(channel):
    prefix, suffix = channel.split(".")
    return prefix[:-1]
channels = [["ch1a.twist", "ch1b.twist", "ch1c.twist", "ch2a.bop", "ch2b.bop", "ch3c.pull"]]
result = [next(v) for k,v in itertools.groupby(channels[0], key=channel_name)]
print(result)

Result:

['ch1a.twist', 'ch2a.bop', 'ch3c.pull']

Upvotes: 1

Related Questions