Python: How to write this python one-liner in 'readable' way? - python

I have started to learn Python. I very confused with one-liner used in this code (5th line in the below code).
Can someone please explain to me how this one liner is working? May be re-write in verbose way?
multiset = [2, 2, 3, 3, 4, 5, 6, 7, 8, 10]
x = [0]
deltaSet = set(multiset)
for candidate in deltaSet:
if sum([(abs(candidate-member) in multiset) for member in x]) == len(x):
for member in x:
multiset.remove(abs(candidate-member))
x.append(candidate)
if len(x) == n: break
Thanks!

I believe the line you are looking at is:
sum([(abs(candidate-member) in multiset) for member in x])
First, there are far too many parenthesis there. Lets get rid of the stuff we don't need:
sum(abs(candidate-member) in multiset for member in x)
Phew, that's a little better already. Now lets actually look at the expression piece by piece:
abs(candidate - member) in multiset
This is self explanatory enough ... Is the absolute value of the candidate minus the member in the multiset? If yes, the expression returns True, if not, the expression returns False. Now what are the member? Well, there's one for each thing in the iterable x. So you're summing a bunch of True and False. In python, booleans are subclassed from int (with True == 1 and False == 0), the sum is basically counting the number of times that expression we talked about earlier is True.
Then they check if it is equal to the len(x) so basically, the code is checking if the expression is True for every member in x. Fortunately, there's a better way to write this in python:
all(abs(candidate - member) in multiset for member in x)
If this is still confusing, we could rewrite this as a function (lets call it f(x):
def f(x):
"""Equivalent to `all(abs(candidate - member) in multiset for member in x."""
for member in x:
if not abs(candidate - member) in multiset:
return False
return True
For some reference reading, in both cases, I've used generator expressions (which are similar to list-comprehensions in syntax and meaning, but they generate the items "yielded" on the fly rather than materializing an entire list at once. They're more memory efficient and faster for some operations. They're particularly useful for cases where you don't need to look at every item to know the result (e.g. this one where a single False is enough to make the entire expression False).

Related

```while [List]: ``` vs ```while [List] is True```? What is the difference?

while [List]: vs while [List] is True? What is the different?
For example I am doing this problem (heap and priority queues) https://leetcode.com/problems/find-k-pairs-with-smallest-sums/ and here is a sample solution that I retrieved. I do not understand this line while len(res) < k and heap:. Why do I need while heap:? and Also when I tried while ... heap is True, the code no longer works.
class Solution:
"""Returns List[List[int]]"""
def kSmallestPairs(self, nums1, nums2, k):
# nums1 and nums2 are both sorted list
res = []
if not nums1 or not nums2 or not k:
return res
heap = []
visited = set()
heapq.heappush(heap, (nums1[0] + nums2[0], 0, 0))
visited.add((0, 0))
while len(res) < k and heap:
_, i, j = heapq.heappop(heap)
res.append([nums1[i], nums2[j]])
if i + 1 < len(nums1) and (i + 1, j) not in visited:
heapq.heappush(heap, (nums1[i + 1] + nums2[j], i + 1, j))
visited.add((i + 1, j))
if j + 1 < len(nums2) and (i, j + 1) not in visited:
heapq.heappush(heap, (nums1[i] + nums2[j + 1], i, j + 1))
visited.add((i, j + 1))
return res
There are a few different things necessary to fully understand the topic you're asking about.
The first is what do the is operator does. It checks for identity, that is, if A is B is true, then A and B must be two references to the same object.
The second is boolean contexts. When you use an expression in a if or while statement's condition, or pass it as the first argument to the and or or operators (or the only argument to the unary not operator), Python will implicitly convert your object into a bool value before considering if the condition is passed or not. Different types may handle this conversion differently, by implementing whatever logic they want in their __bool__ method. For the builtin types, bool(o) is False only for numerical values that are equal to zero, and for container objects that are empty (and None is always falsey). All other values are truthy (as are instances of user-created classes, by default).
Note the terminology I'm using here. When dealing with boolean contexts, we often talk about "truthiness" rather than something being true or false. An object o is "truthy" if bool(o) is True, and "falsey" if bool(o) is False. A truthy value isn't generally equal to True. And while a bunch of numerical falsey values are equal to False (because False is equal to zero), other kinds of falsey values (like empty strings and empty lists) are not equal to either zero or False.
In the code you're asking about, a list named heap is tested in a boolean context. That means the condition will be true (and the while loop will keep going) if the list is non-empty. You can see why that's important by looking at the very first line of the loop body, where heapq.heappop is called on the list. That function will raise an exception if heap is empty, so the code stops the loop if that's the case.
Testing heap is False is not remotely equivalent, because heap is a list, and so it will never be a reference to the same object as the False literal. In some situations it might make sense for a loop condition to use is, but this is definitely not one of those situations.
Writing bool(heap) is True could make some amount of sense, but it's unnecessary, since just heap (in the context of a while loop's condition) works just as well.
If you want to be more explicit about the check, you could test the length of the list directly, with len(heap) > 0. This is also longer than just using heap by itself, but it might be worth writing anyway if you feel it is more expressive of the meaning you intend (though experienced Python programmers will understand what heap means in a boolean context).
(I'd further note that your question was a bit more confusing than it needed to be because you're using [List] as a sort of pseudocode meaning "some kind of list", despite the fact that that string is valid Python syntax. Without your textual explanation, I'd expect [List] to mean a one-element list containing a value named List, which would always be truthy, since it's not empty. Avoiding ambiguous notation in your questions will help you get quicker and better answers to your questions.)
any data can be True or False
remember this:
0 -> False (but be care '0' as string is True, because it's a string that not equal to '' empty one)
'' -> False (empty string = False)
[] -> False (empty list, empty tuple, empty set, empty dict = False)
[] - this is False
['something'] - this is True
so when you see things like this: if [list] or while [list]
you should see them like:
if [this list is not empty]
while [this list is not empty == while it's True]
so this while len(res) < k and heap means:
while length of res < k and heap is True (-> not empty, not 0, not False)

what's the difference between filter and comprehention with if?

def anagramwordchecker(z,w):
if sorted([x for x in w])==sorted([x for x in z]):return True
return False
def anagramlistchecker(l,w):
d={}
for x in w:
d.update({x:w.count(x)})
l=list(filter(lambda x:anagramwordchecker(x,w),l))
return l
print(anagramlistchecker(['bcda', 'abce', 'cbda', 'cbea', 'adcb'],'abcd'))
trying to check which words are anagram.
using both of this it will print the same:
l=[x for x in l if anagramwordchecker(x,w)]
l=list(filter(lambda x:anagramwordchecker(x,w),l))
and it will be:
['bcda', 'cbda', 'adcb']
then what's the difference? any advantage using filter? cause comprehension is easier.
If you print the results of the following example, you will know which one is faster (Comments are results I got).
timeit.Timer('''[x for x in range(100) if x % 2 == 0]''' ).timeit(number=100000)
timeit.Timer('''list(filter(lambda x: x % 2 == 0, range(100)))''').timeit(number=100000)
# 0.3664856200000486
# 0.6642515319999802
So in your case, list comprehension would be faster. But let's see the following example.
timeit.Timer('''[x for x in range(100) if x % 2 == 0]''' ).timeit(number=100000)
timeit.Timer('''(x for x in range(100) if x % 2 == 0)''' ).timeit(number=100000)
timeit.Timer('''filter(lambda x: x % 2 == 0, range(100))''').timeit(number=100000)
# 0.5541256509999357
# 0.024836917000016
# 0.017953075000036733
The results show that casting an iterable to list takes much time and filter is faster than generator expression. So if your result does not really have to be a list, returning an iterable in a timely manner would be better.
As stated in here,
Note that filter(function, iterable) is equivalent to the generator expression (item for item in iterable if function(item)) if function is not None and (item for item in iterable if item) if function is None.
But list comprehension can do much more than simply filtering. If filter is given to the interpreter, it will knows it is a filter function. However, if a list comprehension is given to the interpreter, the interpreter does not know what it really is. After taking some time interpreting the list comprehension to something like a function, it would be a filter or filterfalse function in the end. Or, something else completely different.
filter with not condition can do what filterfalse does. But filterfalse is still there. Why? not operator does not need to be applied.
There is no magic. Human-friendly 1-for-many grammars are based on encapsulation. For them to be machine-executable binaries, they need to be decapsulated back and it takes time.
Go with a specific solution if it is enough than taking a more general solutions. Not only in coding, general solutions are usually for convenience, not for best results.

Python all()/any() like method for a portion/part of list?

What would be the most elegant/pythonic way of achieving: "if x% of total values in a list are greater than the y, return true". I have currently implemented a function:
def check(listItems, val):
'''A method to check all elements of a list against a given value.
Returns true if all items of list are greater than value.'''
return all(x>val for x in listItems)
But for my use case, waiting for this particular condition is quite costly and somewhat useless. I would want to proceed if ~80% of the items in list are greater than the given value.
One approach in my mind is to sort the list in descending order, create another list and copy 80% of the elements of list to the new list, and run the function for that new list. However, I am hoping that there must be a more elegant way of doing this. Any suggestions?
It sounds like you are dealing with long lists which is why this is costly. If would be nice if you could exit early as soon as a condition is met. any() will do this, but you'll want to avoid reading the whole list before passing it to any(). One options might be to use itertools.accumulate to keep a running total of True values and the pass that to any. Something like:
from itertools import accumulate
a = [1, 2, 2, 3, 4, 2, 4, 1, 1, 1]
# true if 50% are greater than 1
goal = .5 * len(a) # at least 5 out of 10
any( x > goal for x in accumulate(n > 1 for n in a))
accumulate won't need to read the whole list — it will just start passing the number of True values seen up to that point. any should short-circuit as soon as it finds a true value, which in the above case is at index 5.
What about this:
def check(listItems, val, threshold=0.8):
return sum(x > val for x in listItems) > len(listItems) * threshold
It states: check is True if more than threshold% (0.80 by default) of the elements in listItems are greater than val.
You can use filter for this. By far this is the fastest method. Refer to my other answer as this is faster than the methods in that.
def check(listItems, val, goal=0.8):
return len((*filter(val.__lt__, listItems),)) >= len(listItems) * goal
Tested result time for this ran along with the methods in my other question is:
1.684135717988247
Check each item in order.
If you reach a point where you are satisfied then return True early.
If you reach a point where you can never be satisfied, even if every future item passes the test, then return False early.
Otherwise keep going (in case the later elements help you satisfy the requirement).
This is the same idea as FatihAkici in the comments above, but with a further optimization.
def check(list_items, ratio, val):
passing = 0
satisfied = ratio * len(list_items)
for index, item in enumerate(list_items):
if item > val:
passing += 1
if passing >= satisfied:
return True
remaining_items = len(list_items) - index - 1
if passing + remaining_items < satisfied:
return False
I don’t want to take credit for Mark Meyer’s answer as he came up with the concept of using accumulate and any as well as theirs being more pythonic/readable, but if you’re looking for the "fastest" approach then modifying his approach with using map vs using comprehensions is faster.
any(map(goal.__le__, accumulate(map(val.__lt__, listItems))))
Just to test:
from timeit import timeit
from itertools import accumulate
def check1(listItems, val):
goal = len(listItems)*0.8
return any(x > goal for x in accumulate(n > val for n in listItems))
def check2(listItems, val):
goal = len(listItems)*0.8
return any(map(goal.__le__, accumulate(map(val.__lt__, listItems))))
items = [1, 2, 2, 3, 4, 2, 4, 1, 1, 1]
for t in (check1, check2):
print(timeit(lambda: t(items, 1)))
The results are:
3.2596251670038328
2.0594907909980975

Check if all the elements in that list are divisible by some given integer or not

Given a list, I wanted to check if all the elements in that list are divisible by some given integer or not. Based on that, i have to return a boolean value.
l=[10,30,40,20]
For example - all the elements of this list are divisible by 5. Then, I would return True.
For 6, I would have returned False.
One approach I could think of is to generate an array consisting off boolean values and then AND them.
blist=[x%5==0 for x in l]
# [False, False, False, False]
# AND THE ELEMENTS
But this approach kind of feels bad. Can anyone suggest a more simple pythonic way out of this.
First of all, you want modulo division (%) as you want to see if it evenly divides by 5, so you are checking for a remainder, not the result of division.
You can use the all() builtin (which does what it says on the tin), but you don't need to generate a list, instead use a generator expression:
all(x%5 == 0 for x in l)
This has the advantage of being lazy, so as soon as a value isn't divisible it will return, saving computation
Using list comprehensions is pythonic. And you need to use mod not div.
Use all built in
res = all([x%5==0 for x in l])
You can do this more efficiently by
res = all(x%5 == 0 for x in l)
which uses a generator expression. In the first case python generates a list of all the mod values, in the second case the values are generated as they are needed by all and are hence only generated up to the first non-divisible value.

Does python have a shorthand for this simple task?

I've just started to learn the long-heard python language. I've been working with C before. And I find python, as a modern script language is much concise on various tasks.
So I was wondering, if I have a list foo = [1, 2, 3, 4, 5], and I want to pick all the odd numbers out of it into bar. In C, I might use a loop and check each number in foo and copy the elements needed into bar. What do you guys do this "python-style"?
bar = [x for x in foo if x % 2 == 1]
This form is called "list comprehension". In its basic form, it has 4 parts:
What you want to include in the output list. Can be any expression involving the variable(s) defined in the second part (below). In this case, the element x, unmodified;
A variable, or expression, denoting an element of the input list. Following the for keyword, each element of the list will be bound to that variable (if your list contains complex objects, you can use destructuring assignment to refer only to specific parts of it). In this case, each item of the list is bound to x;
The input list. Following the in keyword, the list (or other iterable) where you'll get your elements from. In this case, foo;
A condition that the element must meet to be included in the result (optional). If included, add the keyword if followed by an expression to determine whether or not that element will be included in the output list. In this case, it will be if the number is odd.
filter function is what you are looking for:
bar = filter(lambda x: x % 2 == 1, foo)
The expression lambda x: x % 2 == 1 is basically equivalent to
def isOdd(x):
return x % 2 == 1

Categories