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.
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+
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.
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
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)
Related
I have a control statement as following:
if x < 0 or x >= ht or y < 0 or y >= wdt:
im_warped[i][j] = 0
else:
im_warped[i][j] = im[x][y]
which gives the same result as following:
if 0 < x < ht and 0 < y < wdt:
im_warped[i][j] = im[x][y]
I am not specifying an else case for the second control statement, eventhough I am sure that such values (exceeding the bounds) do exist. So what exactly is happening here? Do they automatically get assigned to zero / null values (which I think is unlikely)
If you don't have an else block, then nothing else will happen to the data. Your im_warped array will only have an entry modified in accordance with your if statement
The answer to your question, then, depends on what happens to that data before reaching this if statement. If it's a numpy array created with np.zeros, then all of its entries are 0 by default. If it's data that you're getting from somewhere else, those default values could be anything and depend on what the input data looks like.
if statements have blocks, not values. You seem to be confusing this with the ternary operator. For instance, in Tableau, if you write
if condition then
x
else
y
end
then when condition is true, this whole statement will be evaluated as having the value of x. If you write
z = if condition then x else y end
then whenever condition is true, the expression if condition then x else y will be evaluated as being x, and so x will be assigned to z.
In Python, however, if you write
if condition then:
x
Python expects x to not be a value, but an instruction. In your first example, you had im_warped[i][j]=0. This is an instruction: it tells Python to assign 0 to im_warped[i][j]. If you were to write
z = if condition:
x
else:
y
that will return an error in Python, because in Python if-then-else is not the ternary operator, it's a control statement. It does not return any values, conditional or default. Rather, it runs code. The "default", to the extent there is one, is to not run any code. When you wrote if x < 0 or x >= ht or y < 0 or y >= wdt: im_warped[i][j] = 0, it is not the if-then-else statement that is returning a value; you are putting a value of 0 within the code that it is running.
There is a ternary operator in Python, but its syntax is slightly different: it is conditional_result if condition else default. So your first example could be written as
im_warped[i][j] = 0 if x < 0 or x >= ht or y < 0 or y >= wdt else im[x][y]
and if you were to write
im_warped[i][j] = im[x][y] if 0 < x < ht and 0 < y < wdt
without an else, that would return an error.
I have a list with elements that I want to do operations on with 2 conditions.
One condition is to multiply a norm function by -1 if the element is negative or leaving the norm function positive if the element is positive.
The list of values looks like this:
print(values)
-97476.70633454417
-93170.30642401175
-89901.82679086612
-87187.62533194348
-87269.09594982903
-85513.31676486236
-83545.26529198853
-82411.91255123452
-81620.01849452594
As you can see they are all negative (in this experiment).
The code looks like this:
norm_BIC = [(-1.0) * float(i)/max(values) for i in values if i < 0 or float(i)/max(values) for i in values if i > 0]
If I run the code before the or statement it works:
norm_BIC = [(-1.0) * float(i)/max(values) for i in values if i < 0]
Which means it's everything else following that doesn't work because I get an empty list for norm_BIC when running after the or.
How do I fix this condition?
It seems that you are simply filtering out the negative values and turning them positive. The abs function takes the absolute value, turning your inputs positive.
would
norm_BIC = [ abs(float(i))/max(values) for i in values]
not fix your problem?
To achieve "this or that" in a list comprehension you need to use an if expression. This allows you to add an else clause as expected —
values = [
-97476.70633454417,
-93170.30642401175,
-89901.82679086612,
-87187.62533194348,
-87269.09594982903,
-85513.31676486236,
-83545.26529198853,
-82411.91255123452,
-81620.01849452594,
]
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values if i > 0]
The syntax here isn't list-comprehension specific, compare to this if expression —
a = 10 if b < 10 else 20
Running your example values without that final if i.e.
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values]
I get the following output.
[-1.1942744945724522,
-1.1415129295794078,
-1.1014678561595233,
-1.0682137414339221,
-1.0692119109931586,
-1.0477002865491576,
-1.0235879240531134,
-1.0097022038381638,
-1.0]
If you just want to ensure the result of your calculation is positive you could use the built-in abs() function.
norm_BIC = [abs(float(i)/max(values)) for i in values]
You should use an else clause:
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values]
There are some related questions on Stack but I wanted to be as clear as possible. I am using Python 3
If I have a list, N, and I use the following code:
N = [1,2,3,4,6,7,8]
for x in N:
N[x] = N[x] * -1
return N
I am getting a Index out of range error. I understand you shouldn't be adding and deleting elements while iterating over a list, but I wanted a clear definition of why the above example won't work.To me, it seems like there shouldn't be a problem. In the first iteration, x should evaluate to 1. So if I want to edit N[1], I don't see why I wouldn't be able to.
As a side note, I know enumerate() is the proper way to do it.
Use enumerate
Ex:
N = [1,2,3,4,6,7,8]
for x, value in enumerate(N):
N[x] = value * -1
print(N)
or a list comprehension.
Ex:
N = [x * -1 for x in N]
In for x in N:, x takes on each value in N, then you use it like an index. Lists in Python are 0-indexed, so you get an Index out of range error when you reach the end of the list and try to access N[8], which doesn't exist. You can use for x in range(len(N)): instead.
The problem here is actually a little different: you're treating members of the list as if they were indices of the list. Since N[8] doesn't exist, that's where your error is coming from. I think what you meant to do was:
N = [1,2,3,4,6,7,8]
for x in range(len(N)):
N[x] = N[x] * -1
return N
In the first iteration, x=1 which means N[1] equals 2 and so your new N[1] becomes 2 * -1 = -2. Now when x is 8 since you are using for x in N, your code tries to access N[8] but since the length of N is 8, the indexing starts from 0 and goes up to 7. Hence there is no index 8 and hence you get an error Index out of range error
Use good ol' lambda's or a specific callable in list comprehension:
lambda:
N = [1,2,3,4,6,7,8]
M = [(lambda x:-x)(element) for element in N]
print(M)
callable/function:
def negate(x):
return -x
N = [1,2,3,4,6,7,8]
M = [negate(element) for element in N]
print(M)
In your code here -
N = [1,2,3,4,6,7,8]
for x in N:
# x will be 1, 2, 3, 4
And the way you are accessing is -
N[x]
But indices run from 0 to n-1, where n-1 is the last element. Also, in your list, you are missing a 5 so indices will change badly. If you had
N = [1,2,3,4,5,6,7,8]
your code would have worked fine. But since that's not the case, you'd have to use range like -
for i in range(len(N)):
N[i] = N[i] * -1
You are enumerating in a wrong way
N = [1,2,3,4,6,7,8]
for i, x in enumerate(N):
N[i] = N[i] * -1
return N
I am doing Grok Learning Course, and have come across a problem. Sorry if I have done anything badly; not a professional at coding:
I am trying to make a variable that will be True/False depending on many conditions:
So,
x = True if y > 2 , g < 4 , n != 3
I have tried different ways to do this like:
Assigning variable to each of my conditions:
if y > 2:
ytrue = True
etc..
However, I want to find a better way of doing it than that, which is long and tedious.
Thankyou.
It's as simple as
x = y > 2 and g < 4 and n != 3
which evaluates to True if all three conditions hold and False otherwise.
As you are new to programming, here's how you read it.
First you evaluate the right hand side which is
y > 2 and g < 4 and n != 3
This is evaluated left to right. First it evaluates y > 2 which will either be True or False. If False the whole right hand side is False and False will be assigned to x. Otherwise it keeps on evaluating all of the other sub-expressions on the right hand side until one of them is False or until you've found every one to be True, in which case the whole right hand side is True.
In either case, True or False, your variable x gets the desired value.
x = y > 2 and g < 4 and n != 3
If you have multiple expressions and if you want to do expression on a expression using and's & or's combinations its better to put it on like this
x= ((y > 2 and g < 4) or n != 3)
Comparison operators like (>, <, !=, etc.) all end up being evaluated down to True or False by the python interpreter.
Python also has Boolean the operators and, or, not (Read more in Section 4.2 of the python docs) but you can use these in combination with the comparison operators to chain them. So your assignment becomes:
x = y > 2 and g < 4 and n != 3
You can use ternary conditional operator :
['false','true'][y > 2 and g < 4 and n != 3]
How it works ?
True == 1, False == 0
because booleans are a subclass of int , so [y > 2 and g < 4 and n != 3] produce a integer value but ['false','true'] takes it as index value.
True gives ['false','true'][1]
And False gives ['false','true'][0]
Test case:
y=4
g=1
n=3
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
false
Test case2:
y=4
g=1
n=1
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
true
Now, if you want you can store the result in a variable :
x=['false','true'][y > 2 and g < 4 and n != 3]
which you wanted i think.
m = range(1, 2000000, 2)
sum1 = 2
for x in xrange(1, 2000000, 2):
for y in m:
if x != y:
if x%y == 0:
m.remove(x)
if all(x%y != 0):
sum1 += x
That's what I've written. It's about a problem, trying to add all the primes bellow two million. My problem is in the all() statement. What I want to happen is to check if x is a prime; that is true only if every x%y gives a remainder.
Also if I use a can I use a statement (break?) to stop the loop if y > x/3 like so:
m = range(1, 2000000, 2)
sum1 = 2
for x in xrange(1, 2000000, 2):
for y in m:
if y > x/3:
break
else:
if x != y:
if x%y == 0:
m.remove(x)
if all(x%y != 0):
sum1 += x
You have to pass a sequence or iterable to all -- it just tests whether or not all the items passed to it evaluate as true. Here's the right way to use all:
>>> all([True, True, True])
True
>>> all([True, False, True])
False
>>> all([x > 5 for x in range(10)])
False
>>> all([x > 5 for x in range(6, 10)])
True
>>> all(x > 5 for x in range(6, 10))
True
That last one is the best, because it takes advantage of short-circuiting.
However, your call to all in your code is pointless. The idea behind your code, it seems to me, is to go through all the values in m and remove those that are divisible by any number between 2 and 2000000. Once you've done that, m will contain only prime numbers.
Of course, your code still won't work if you remove all. That's because you're actually testing whether each number in m is divisible by the numbers [1, 3, 5, 7...1999999]. (That's the sequence signified by xrange(1, 2000000, 2). Because you start at 1, and everything is divisible by 1, your code will count nothing as prime. And then, once you remove 1 from that sequence, anything divisible by 2 will be counted as prime by your code! You should think more carefully about which numbers you actually have to test in your inner loop.
Finally, you should think about how many loops this code will complete. Even once you have this working, it will take a very long time to generate a result. You should test it on smaller numbers first; and then, you should think about how to reduce the number of loops. (And -- only after you've thought about it a bit -- read this.)
But once you have this working, all you have to do is call sum on your list of primes.
Your use of all is incorrect, if you look at the documentation for it, it takes an iterable.
What you may be trying to do is use a generator expression, something of the form:
sum(x**2 for x in range(10))
which is very similar to the list comprehension
[x**2 for x in range(10)]
However, use of all in this manner wouldn't suddenly stop the generator expression, if it found a divisor. Use of any and checking for x == 0 would stop sooner, but as the code is currently formatted, would check for many divisors before deeming something prime.
This would be more appropriate:
primes = []
MAX = 2000000
number = 2
while number < MAX:
for prime in primes:
if number % prime == 0:
number += 1
continue
primes.append(number)
number += 1
total = sum(primes)
all() takes an iterable for an argument. In your situation, you would use it like this:
all(x%y for y in m)
where x%y for y in m is a generator expression.
If I have an iterable
[item1, item2, item3, item4...]
all(iterable) is equivalent to:
item1 and item2 and item3 and item4...'