29

I'm trying to find minimum element in matrix row, but there are two conditions: 1) it must be > 0 2) and this point must be not visited(is_visited[k] is False) I'm trying to do next:

min(x for x in matr_sum[i] if x > 0  if is_visited[k] is False )

But there is an error: min() arg is an empty sequence

The full block of code:

for k in range(4):
        if matr_sum[i][k] == min(x for x in matr_sum[i] if x > 0  if is_visited[k] is False ) and i!=k:
            return k

How to resolve it? Or should I write my min() function? Because it works with one condition:

min(x for x in matr_sum[i] if x > 0)

But with two conditions, it doesn't work.

Andrew
  • 391
  • 2
  • 4
  • 12
  • 1
    What's the question? – Steve Jessop Nov 24 '14 at 21:46
  • 1
    so, min cannot find the minimal value in an empty sequence. makes sense. it is really up to you to figure out what you want to do about the empty sequence. – njzk2 Nov 24 '14 at 21:48
  • it works with one condition. Why it doesn't with two? – Andrew Nov 24 '14 at 21:49
  • 1
    @Andrew: it doesn't work with two conditions because none of the values of `x` that you iterate over, pass both conditions. There's nothing for `min` to see, so it throws an exception. – Steve Jessop Nov 24 '14 at 21:51
  • 1
    It is Invalid Syntax – Andrew Nov 24 '14 at 21:52
  • To add to the above, if you print `[x for x in matr_sum[i] if x > 0 if is_visited[k] is False]` before the problematic line, you will see that in the case that errors, the list is empty. `min([])` raises this exception, because its not obvious/defined what the minimum of no items should be. – Tom Dalton Nov 24 '14 at 21:52
  • related: https://stackoverflow.com/questions/72134168/how-does-one-save-a-plot-in-wandb-with-wandb-log – Charlie Parker May 05 '22 at 22:16

4 Answers4

39

If you want to avoid this ValueError in general, you can set a default argument to min(), that will be returned in case of an empty list. See described here.

min([], default="EMPTY")
# returns EMPTY

Note that this only works in Python 3.4+

patrick
  • 4,455
  • 6
  • 44
  • 61
11

There is no problem with the syntax. It's certainly unusual to have two if clauses, but it's allowed. Consider:

print(min(x for x in range(1,300) if x % 3 == 0 if x % 5 == 0))

Output:

15

However:

print(min(x for x in range(1,300) if x % 2 != 0 if x % 2 != 1))

Output:

ValueError: min() arg is an empty sequence

There are no integers that are both odd and even, so there are no values for min to see, so it throws an exception.

I deduce that in your code, there are no values that pass both conditions. Python doesn't allow you to compute "the minimum of no values", mainly because it makes no sense.

You have to decide what you want to do in the case where there is no minimum because there are no values greater than 0. For example, if you don't want to return k in that case then I might re-write your code something like this:

for k in range(4):
    if k != i and is_visited[k] is False:
        if matr_sum[i][k] > 0 and matr_sum[i][k] == min(x for x in matr_sum[i] if x > 0):
            return k

It might not be obvious why this helps, but assuming matr_sum[i] is a list or similar, then once we know matr_sum[i][k] > 0 then we know the generator passed to min isn't empty, so we won't get an exception. Whereas if matr_sum[i][k] <= 0, then it certainly isn't equal to the smallest positive value, so there's no need to compute the min at all. Another way to write that would be:

if matr_sum[i][k] > 0 and not any(0 < x < matr_sum[i][k] for x in matr_sum[i])

Actually, I'd normally write if not is_visited[k], but I leave it as is False since I don't know whether changing it would change the behaviour of your code.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
2

Try this - it creates the list of x values xs and then only tries to find the min if xs is non-empty. You may need to add some logic to handle the case that xs is empty, depending on what your code is doing.

for k in range(4):
    if is_visited[k] is False and i != k:
        xs = [x for x in matr_sum[i] if x > 0]
        if xs and matr_sum[i][k] == min(xs):
            return k
Tom Dalton
  • 6,122
  • 24
  • 35
1

Just use and operation for concatenate tow if statement :

min(x for x in matr_sum[i] if x > 0 and if is_visited[k] is False and i!=k)
Mazdak
  • 105,000
  • 18
  • 159
  • 188