Python function and list not working as expected
Question:
I created a fairly simple function; however, it isn’t performing as desired. I think i’m missing something with my if line but not sure.
I have two lists. I want to take the first number of list 1 and see if it is the same number as the first number in list 2. Then I want to do that all the way through.
I should end with 17 ‘Yes’ responses in my list (l)
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def fix(x,y):
l = []
for i in x:
if i == y:
l.append('yes')
else:
l.append('no')
return(l)
fix(labels, preds)
Answers:
You are comparing the elements of x to the variable holding list y, which will always be false.
To accomplish this easiest in a pythonic way use zip, as below:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def fix(x,y):
l = []
for i,j in zip(x,y):
if i == j:
l.append('yes')
else:
l.append('no')
return l
fix(labels, preds)
Zip returns a tuple with the elements of each list at a given index: https://www.programiz.com/python-programming/methods/built-in/zip
Here is a list comprehension that does what you want in one line:
['yes' if i == j else 'no' for i, j in zip(preds, labels)]
If you wanted to see if all element of one list appear in another list in that order (with possible extra elements in the second list), this would be an approach:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def contained_in_order(xs: list, ys: list) -> bool:
i = 0
try:
for x in xs:
i = ys.index(x, i) + 1
return True
except ValueError:
return False
print(contained_in_order(labels, preds))
This prints True
for the lists you provided as labels
is indeed contained in pred
in order.
Howevever, a list of 'yes'
and 'no'
values wouldn’t make sense in this context, since there may be many ways to match. For example, consider:
preds = [1, 0, 1]
labels = [0, 0]
Clearly, labels
is not contained in preds
in order. But both [1, 0]
and [0, 1]
would be. So should the result be ['yes', 'no']
or ['no', 'yes']
?
You could write a function that generates all possible mismatches, but I doubt that’s what you’re after. Perhaps you can update the question to clarify what exactly you’re trying to achieve, or comment on the answer.
Edit: If you’re just after a list of matches, which you say you’d like to see as strings, this is all you need:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
yes_no = ['yes' if p == l else 'no' for p, l in zip(preds, labels)]
print(yes_no)
Output:
['yes', 'yes', 'yes', 'yes', 'no', 'no', 'no', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'no', 'no', 'yes']
I created a fairly simple function; however, it isn’t performing as desired. I think i’m missing something with my if line but not sure.
I have two lists. I want to take the first number of list 1 and see if it is the same number as the first number in list 2. Then I want to do that all the way through.
I should end with 17 ‘Yes’ responses in my list (l)
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def fix(x,y):
l = []
for i in x:
if i == y:
l.append('yes')
else:
l.append('no')
return(l)
fix(labels, preds)
You are comparing the elements of x to the variable holding list y, which will always be false.
To accomplish this easiest in a pythonic way use zip, as below:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def fix(x,y):
l = []
for i,j in zip(x,y):
if i == j:
l.append('yes')
else:
l.append('no')
return l
fix(labels, preds)
Zip returns a tuple with the elements of each list at a given index: https://www.programiz.com/python-programming/methods/built-in/zip
Here is a list comprehension that does what you want in one line:
['yes' if i == j else 'no' for i, j in zip(preds, labels)]
If you wanted to see if all element of one list appear in another list in that order (with possible extra elements in the second list), this would be an approach:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
def contained_in_order(xs: list, ys: list) -> bool:
i = 0
try:
for x in xs:
i = ys.index(x, i) + 1
return True
except ValueError:
return False
print(contained_in_order(labels, preds))
This prints True
for the lists you provided as labels
is indeed contained in pred
in order.
Howevever, a list of 'yes'
and 'no'
values wouldn’t make sense in this context, since there may be many ways to match. For example, consider:
preds = [1, 0, 1]
labels = [0, 0]
Clearly, labels
is not contained in preds
in order. But both [1, 0]
and [0, 1]
would be. So should the result be ['yes', 'no']
or ['no', 'yes']
?
You could write a function that generates all possible mismatches, but I doubt that’s what you’re after. Perhaps you can update the question to clarify what exactly you’re trying to achieve, or comment on the answer.
Edit: If you’re just after a list of matches, which you say you’d like to see as strings, this is all you need:
preds = [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1]
labels = [1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]
yes_no = ['yes' if p == l else 'no' for p, l in zip(preds, labels)]
print(yes_no)
Output:
['yes', 'yes', 'yes', 'yes', 'no', 'no', 'no', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'no', 'no', 'yes']