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
Related
RTX_number = [int(x) for x in input().split()]
Could someone explain this line of code to me step by step?
I am having great difficulty understanding it.
As far as I know, .split creates spaces between elements?
I saw this code on a forum and I am trying to get a better understanding of it because I think it might be helpful for a simulation project.
I heard this is called a list comprehension, but I am kind of lost as of for now.
input().split()
Reads a line and breaks it where ever there is a space into a list of strings.
for x in input().split()
Takes this list, runs over it item by item, and binds this item to x.
int(x) for ...
Takes this x we bound, and runs int(x) on it and returns it.
[int(x) for x in input().split()]
Takes all these results and puts them into a list.
The short version is that this:
RTX_number = [int(x) for x in input().split()]
is a short-form of this:
RTX_number = []
for x in input().split():
RTX_number.append(int(x))
where input().split() returns the list of strings that you get from separating whatever input() returned on each whitespace (for example, "Hello World" becomes ["Hello", "World"].
The str.split() function can also be given an argument, such as ',', which it will split on instead of whitespace.
The general syntax of a comprehension is
(expression) for (element) in (iterable) if (condition)
For every element element in the iterable, if the condition resolves to True (note that the condition can be omitted entirely) the expression is evaluated and added to the returned list.
We usually use comprehensions as shorthand for full loops, since they often save space and complexity.
Note that list comprehensions aren't the only kind of comprehension - they can be used to make several different data structures:
# list comprehension - produces a list
[expression for element in iterable]
# set comprehension - produces a set instead of a list
{expression for element in iterable}
# dict comprehension - produces a dict with key-value pairs
{key:value for element in iterable}
# generator comprehension - like a list comprehension, but each expression is not
# actually evaluated until something tries to read it.
# The parentheses are technically optional, if the syntax isn't ambiguous
(expression for element in iterable)
This code is equivalent to:
# ask user input (it expected something like "1 2 34 5")
input_text = input()
# split on spaces
split_text_list = input_text.split()
list_of_integers = []
# for each string item in list
for item in split_text_list:
# convert to integer
number = int(item)
# add to list
list_of_integers.append(number)
But of course it avoids having all the unnecessary intermediate variables, so it is shorter. Also faster as it doesn't require to store the intermediate values.
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.
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).
Input:
['mia', 5, 10]
['mia', 20, 50]
['mia', 52, 101]
['mia', 220, 380]
My code (which works but I'd like to get it automated without typing print by hand all the time):
print lines[1][1] - lines[0][2]
print lines[2][1] - lines[1][2]
Output:
10
2
119
To automate this printing process I tried using a for loop:
for x in lines:
print lines[x][1] - lines[x-1][2]
And received the error: TypeError: list indices must be integers, not list
Then I tried:
for int(x) in lines:
print lines[int(x)][1] - lines[int(x)-1][2]
And received the error: SyntaxError: can't assign to function call
I examined Subtracting a value from all elements of a 2D list in python but it did not help me to figure out my problem.
Any help is appreciated to get my arithmetic process automated (either using a for loop so I can understand how I could improve my code above, or some other structure). Bonus points for showing how to define a function or create a class definition to accomplish this task.
In the first case x in lines means x takes the value of each line. I.e., first x = ['mia', 5, 10], then x = ['mia', 20, 50]... This isn't what you want. You want x = 0, x = 1...
But by trying to simply making x into an integer by writing int(x) what you are saying is on the first iteration of the loop assign ['mia', 5, 10] to int(x), and so on. But the left hand side is a function call, meaning take x and convert it to an int, and you can't assign something (a list in this case) to a function call.
What you really want to do is change the right hand side of your looping expression. Instead of going through the list elements you want to go through the list indices.
for x in range(1,len(lines)):
print lines[x][1] - lines[x-1][2]
try this, just a join of the loop placed in a print statement for the \n to trigger
print '\n'.join(str(lines[x][1]-lines[x-1][2]) for x in xrange(1,len(lines)))
You can also go crazy without using range for indices:
for (first, second) in zip(lines[:-1], lines[1:]):
print second[1] - first[2]
zip or izip (there are slight differences in Python2) create tuples from all iterables that they are given. From the docs:
This function [zip] returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
Since the order of lists is guaranteed, this will yield the elements offset by the slices introduced.
Here the first iterable is all the lines without the last and the second iterable is all the lines excluding the first (0 index).
You should do :
for x in range(1,len(lines)):
#do something
this will loop from 1 to len(lines) - 1
I am quite new to Python 2.7 so I had a couple of questions regarding using for loops to while loops.
For example: I am writing this definition
def missingDoor(trapdoor,roomwidth,roomheight,step):
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
for m in hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
for e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
i += 1
return sorted(safezone)
I am trying to turn all the for loops to a while loops, so this is currently what I have written so far. I actually dont know if we say "While e in " works near the middle of the code. But using the while loop rules, will this code do the same as the for loop one?
safezone = []
hazardflr = givenSteps(roomwidth,step,True)
safetiles = []
m=0
while m < hazardflr:
safetiles.append((m,step))
i = 0
while i < len(safetiles):
nextSafe = safetiles[i]
if knownSafe(roomwidth, roomheight, nextSafe[0], nextSafe[1]):
if trapdoor[nextSafe[0]/roomwidth][nextSafe[0]%roomwidth] is "0":
if nextSafe[0] not in safezone:
safezone.append(nextSafe[0])
e=0
while e in givenSteps(roomwidth,nextSafe[0],True):
if knownSafe(roomwidth, roomheight, e, nextSafe[0]):
if trapdoor[e/roomwidth][e%roomwidth] is "0" and (e,nextSafe[0]) not in safetiles:
safetiles.append((e,nextSafe[0]))
e+=1
i += 1
m+=1
return sorted(safezone)
thanks for any advice or help!
No, your code isn't identical.
While they look similar, for item in list and while item in list will do wildly different things.
for item in list is a syntactic way of saying for every item in the list - do something with is.
while item in list is different - a while loop iterates as long as the condition is true. The condition in this case being item in list. It doesn't update the item each iteration and if you never change what item or list are, it might never terminate. Additionally, if any given item isn't in the list it may terminate prematurely.
If you want to iterate through a list and keep a count, using while is the wrong way to go about it. Use the enumerate() function instead.
enumerate() takes a list, and returns a list of tuples, with each item from the list in order with its index, like so:
for i,m in enumerate(hazardflr):
safetiles.append((m,step))
This small change means you no longer have to track your indices manually.
If you are iterating through every item in a list in Python - use for that's what it is designed to do.
It depends on exactly what givenSteps returns, but in general, no. for x in foo evaluates foo once and then assigns x to be each element of foo in turn. while x in foo: ... x += 1, on the other hand, evaluates foo on every iteration and will end early if foo is not a contiguous sequence. For example, if foo = [0, 1, 2, 5, 6], for will use every value of foo, but while will end after 2, because 3 is not in foo. while will also differ from for if foo contains any non-integral values or values below the starting value.
while aList:
m= hazardflr.pop()
# ...
should be roughly equivelent to your other loop