Let's say I have a Python list that might contain any combination of members from the following two tuples:
legal_letters = ('a', 'b', 'c')
legal_numbers = (1, 2, 3)
So legal combination lists would include
combo1 = ['a', 1, '3']
combo2 = ['c']
combo3 = ['b', 2, 1, 'c']
Any length, any combination. You can assume no duplicated characters will be in the combination list though. I'd like to apply a function to those combinations that modifies them (in place) such that they contain at most a single member of one of the tuples -- say it's numbers. The 'chosen' member of the number tuple should be selected at random. I also don't care if order gets mangled in the process.
def ensure_at_most_one_number(combo):
# My first attempts involved set math and a while loop that was
# pretty gross, I'll spare you guys the details. I'm sure I could get it to work
# but I figured there might be a one-liner or some fancy itertools out there
return combo
# Post transformation
combo1 = ['a', '1']
combo2 = ['c']
combo3 = ['c', 'b', 2] # Mangled order, not a problem
I can't think of any one-liner to solve this, but I believe this is concise enough.
def only_one_number(combo):
import random
try:
number = random.choice([x for x in combo if x in legal_numbers])
combo[:] = [x for x in combo if x in legal_letters]
combo.append(number)
except IndexError:
pass
In case you don't instantly see the need for the exception handling, we need to catch the IndexError that would result from trying to pass an empty list to random.choice().
Not the best, but it should work
numbers = []
for i in legal_numbers:
if i in combo:
numbers.append(i)
combo.remove(i)
if len(numbers) == 0:
return combo
combo.append(random.choice(numbers))
return combo
Maybe This?
def ensure_at_most_one_number(combo):
i = len(combo) - 1 # start with the last element
found_number = False
while i >= 0:
try:
int(combo[i]) # check element is a number
if found_number == True:
del combo[i] # remove it if a number already found
else:
found_number = True
except ValueError:
pass # skip element if not a number
i -= 1
return combo
Disclaimer: I'm a python beginner myself, so there might be a better way, but this is how I would do it :
import random
def ensure_at_most_one_number(combo, legal_numbers) :
random.shuffle(combo)
first_number = True
for i in range(len(combo)-1, -1, -1) :
if combo[i] in legal_numbers :
if first_number :
first_number = False
else :
del combo[i]
Note that I shuffle the list since you said you wanted to keep a random element. The iteration is done backwards to keep the correct indices after elements have been deleted from the list.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.