lst is a very large list of integers
a,b and c are numbers
code 1
if a in lst or b in lst or c in lst:
print("found in lst")
code 2
if a in lst:
print("found in lst")
elif b in lst:
print("found in lst")
elif c in lst:
print("found in lst")
is there any speed difference in code 1 and code 2
Strictly speaking, both of your code samples will run equally since the or operator supports short-cuiting. That means that Python will not evaluate subsequent conditions unless the one before it evaluated to False. For example, if we have A or B or C, unless both A and B are False, Python will not evaluate C.
The same thing occurs with your if statements: C will only be evaluated if both A and B are False.
However, on large lists, you shouldn't be doing any sort of query like this. If don't need to index the elements of the list, a hash table (Dictionary) is almost always better since you'll get O(1) lookup time.
Related
The following code has multiple loops and I want to reduce it to optimise the time complexity as well.
for a in file1:
if a[0] in [i[1] for i in file2]:
for b in file2:
if a[0] == b[1]:
c.append(int(b[0]))
continue
else:
# do stuff
I tried the following to make it more efficient. Although, I couldn't find an alternative to the if statement.
for a, b in zip(file1, file2):
if a[0] in [i[1] for i in file2]:
if a[0] == b[1]:
c.append(int(b[0]))
continue
else:
# do stuff
Also, the outputs for both the operations are different. The first piece of code does show a correct result.
Your second solution is actually slower. The idea of zip (or rather, it should be like itertools.product, zip produces N pairs) produces NxM pairs, so your entire solution is now O(NxMxM), whereas the first should be O(Nx2M). I'm not sure what your continue statement does, that seems pointless.
My tip is to precalculate some of your values, and to use sets/dictionaries. [i[1] for i in file2] will be the same every loop, so take that out.
Also, since you are aligning b with a by value, let's instead create a reverse lookup dictionary.
# build reverse lookup dictionary
reverse = dict()
for b in file2:
if not b[1] in reverse:
reverse[b[1]] = [b]
else:
reverse[b[1]].append(b)
# check to see if a[0] matches any b[1], if it does append all matching b[0] to c
for a in file1:
if a[0] in reverse:
b_valid = reverse[a[0]]
for b in b_valid:
c.append(int(b[0]))
else:
# do stuff
This brings it down somewhere along the lines of O(N+M) (potentially worse given poor dictionary creation times and lookup times).
Try:
next((x for x in file2 if a[0] == x[1]), None)
That will give you what fits, and you should be able to append if it is not None.
I want to create two random sets and compare them to two other sets.
The programm should stop when both sets are the same as the other two sets.
This is a boiled down version of the code i'm having trouble with:
import random
random.seed()
a = set()
b = set()
c = set()
d = set()
for i in range(3):
a.add(random.randint(1,10))
b.add(random.randint(1,10))
while a!=c and b!=d:
c.clear()
d.clear()
for i in range(3):
c.add(random.randint(1,10))
d.add(random.randint(1,10))
print(a,b)
print(c,d)
The exact line with my problem:
while a!=c and b!=d:
With "and" the loop already stops when just one pair of sets are the same.
When i switch the "and" for "or" it does exacly what i want, i just don't understand why?
Can somebody please explane.
The condition holds when both a is not c and b is not d. As soon as one pair is equal then the and fails and the loop is broken.
As you have identified you could use an or which will work, but it may be more clear to use:
while not (a == c and b == d):
...
which works exactly how you would say it!
Think about it. You have the condition:
a != c and b != d
What exactly is this condition telling Python? Well, we can see it uses the and operator. The and operator will only return True, if both of its conditions are true. From this, we can see that the above condition will only return true if both the a set is not equal to the c set and the b set is not equal to the d set.
So what would happen when one pair of sets becomes equal? The above condition will fail. Since one of the comparisons between two sets would return False, rather than True, and will also return false, since both of its conditions are not true.
What you actually want is this:
not (a == c and b == d)
I'll leave it as an exercise up to you to figure why the above condition works, whereas a != c and b != d does not.
While loops repeat when the statement is True, in this case when either a != c orb != devaluates to False, so will the while loop argument.
You want to alter the logic, change:
a != c and b !=d
to:
not (a == c and b == d)
or:
a != c or b != d
This will achieve what you are after.
You might try:
while not (a == c and b == d):
#code
Doing some basic python coding. Here is the problem I was presented.
Create a function that takes 3 inputs:
Two lists of integers
one integer n
Prints the pairs of integers, one from the first input list and the other form the second list, that adds up to n. Each pair should be printed.
Final Result (Example):
pair([2,3,4], [5,7,9,12], 9)
2 7
4 5
I'm still awfully new to Python, studying for a test and for some reason this one keeps giving me some trouble. This is an intro course so basic coding is preferred. I probably won't understand most advanced coding.
The simplest naieve approach would be to just test all possible combinations to see if they add up.
def pair(list1, list2, x):
for a in list1:
for b in list2:
if a + b == x:
print a, b
There are more efficient ways to do it (eg. ignore duplicates, ignore numbers greater than x, etc.)
If you wanted to do it in a single loop, python has some convenience functions for that
from itertools import product
for a, b in product(list1, list2):
if a + b == x:
print a, b
There are 2 list
a= [1,2,3]
b = [1,2,3]
Now I want to check whether an element from a exist in b or not in python one-liner.
I can use loop on a and then check if it exist in b or not. But I want something pythonic way (one-liner).
bool(set(a)&set(b)) converts a and b into sets and then applies the intersection operator (&) on them. Then bool is applied on the resulting set, which returns False if the set is empty (no element is common), otherwise True (the set is non-empty and has the common element(s)).
Without using sets: any(True for x in a if x in b). any() returns True if any one of the elements is true, otherwise False.
I think you should use sets. This is the way you can do it:
def check_element(a, b):
return not set(a).isdisjoint(b)
len(set(a+b)) < len(set(a)) + len(set(b))
In python, for iterables many one-line iteration commands can be constructed.
For some of such iterations if-statements are required.
Sometimes the order of if-statement and for-statement is important.
Suppose I want to find sum of odd numbers between 0 and 10:
>>> sum(i if not i%2==0 for i in range(10))
SyntaxError: invalid syntax
>>> sum(i for i in range(10) if not i%2==0)
25
Those one-liners are inherently not very comprehensible, however I don't really understand why the if-statement has to come after the for-statement. wouldn't it more fit common sense to use the previous i if not i%2==0 for i in range(10)?
In a generator expression (or a list comprehension), the statements should be listed as if you were nesting them.
Your sum() expression can be nested as:
for i in range(10):
if not i%2 == 0:
# do something with i
You cannot change that ordering, the following would not make sense since i is not defined:
if not i%2 == 0:
for i in range(10):
# do something with i
In your first example, you have an unconditional loop with an if-expression as the list comprehension value. The correct syntax would be:
(a if b else c for i in iterable)
\___________/
|
actual expression
a if b else c is equivalent to a if b evaluates to true, and c otherwise.
In your second example, you have a conditional list comprehension. You are basically skipping over values from the iterable; or more precisely, you are specifying which are taken:
(a for i in iterable if <condition>)
In case of a sum, you can rewrite your list comprehension using the first syntax, as zero is a null element for the addition (and as such the sum):
sum(i if i % 2 != 0 else 0 for i in range(10))