How can I iterate through two lists and compare the values of each in Python?

Question:

Suppose I have the following lists:

x = [0.5, 0.9, 0.1, 0.3, 0.6]

y = [0.4, 0.3, 0.6, 0.1, 0.9]

I want to write a function that iterates through the list and compares each value in order.

 def compare_numbers(prob,thresh):
 output = []
 for x, y in zip(prob, thresh):
   if x >= y:
    output.append(1)
   else:
    output.append(0)
  return output
  compare_numbers(x,y)

This gives me Type Error: 'float' object is not iterable'

Why is this?

I would expect the output to look like this:
[1, 1, 0, 1, 0]

Is there anyway I could write this function such that if the "threshold" value was only one digit it would still work?

My current code to make the latter function is:

def compare_numbers(prob, thresh):
 output = []
 for n in prob:
  if n >= thresh:
   output.append(1)
  else:
    output.append(0)
return output
compare_numbers(x,y)

Yet this returns the Type Error: TypeError: '>=' not supported between instances of 'int' and 'list' when thresh is a list.

Asked By: brandooo23

||

Answers:

The problem is that you are comparing the value n from prob with the entire list thresh. What you need to do is to also iterate over thresh.
Here is a small fix that will allow your code to work:

   def compare_numbers(prob, thresh):
     output = []
     for n in range(len(prob)):
       if prob[n] >= thresh[n]:
         output.append(1)
       else:
         output.append(0)
     return output
Answered By: Franfrancisco9

Psychic debugging:

  1. Your first function is passed a float for either prob or thresh, but the code assumes both inputs are list (really, any iterable) of numbers.

  2. Your second function has the opposite problem, it assumes thresh is a single scalar value (e.g. float), but you passed it as a list.

Seems like confusion on your part; you passed the arguments for the first function to the second and vice-versa. I can’t say exactly how it went wrong, because you didn’t show enough information about how you called the functions, but the tracebacks make the ultimate problem obvious.

If you want a function that accepts either of:

  • A single float
  • A list with some number of floats (that can be extended to match prob if it’s too short)

for thresh, you could do:

from itertools import cycle

def compare_numbers(prob,thresh):
    try:
        iter(thresh)  # Check if it's iterable, so we can wrap if it's not
    except TypeError:
        thresh = (thresh,)  # Convert float to one-tuple of float for compatibility later
    output = []
    for x, y in zip(prob, cycle(thresh)):
        if x >= y:
            output.append(1)
        else:
            output.append(0)
    return output

The loop itself could also be one-lined to just:

return [int(x >= y) for x, y in zip(prob, cycle(thresh)]

or:

return [1 if x >= y else 0 for x, y in zip(prob, cycle(thresh)]

for simplicity and a small performance bump.

Answered By: ShadowRanger

This should work whether thresh is a list, tuple or a single value:

def compare_numbers(prob,thresh):
    if isinstance(thresh, (list, tuple)):
        return [int(x >= y) for x,y in zip(prob,thresh)]
    else:
        return list(map(lambda x: int(x >= thresh), prob))

print(compare_numbers(x,y))

Or:

def compare_numbers(prob,thresh):
    return [int(x >= y) for x,y in zip(prob, thresh)] if isinstance(thresh, (list, tuple)) else [int(x >= thresh) for x in prob]

Output:

# list
x = [0.5, 0.9, 0.1, 0.3, 0.6]
y = [0.4, 0.3, 0.6, 0.1, 0.9]

[1, 1, 0, 1, 0]

# int or float
x = [0.5, 0.9, 0.1, 0.3, 0.6]
y = 0.4

[1, 1, 0, 0, 1]
Answered By: Arifa Chan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.