I'm trying to define a function that returns a list of even integers from a list of overall integers
def print_even_numbers(n: list):
'''Return a list of even numbers given a list of integers'''
for x in list:
if x % 2 == 0:
return(x)
When I tried the code above, the error says that the type isn't iterable
list is the name of the list type. So you cannot iterate over a type. you should use n. Second, your return is indented wrong. It should be on the top function level, because return exits the function. Then you need to collect the result somewhere.
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
result = []
for x in n:
if x % 2 == 0:
result.append(x)
return result
This can be written in short by a list comprehension:
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
return [x for x in n if x % 2 == 0]
Wrong python syntax:
def print_even_numbers(n: list):
You don't need brackets:
return(x)
Wrong indentation. And wrong condition. (And don't use reserved python words such a list for your own variables.
for x in list:
Summarize:
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
result = []
for x in n:
if x % 2 == 0:
result.append(x)
return result
print print_even_numbers(range(10))
>>> [0, 2, 4, 6, 8]
And finally more pythonic way is to use yield to implement desired behaviour:
def gen_even_numbers(n):
for x in n:
if x % 2 == 0:
yield x
print list(gen_even_numbers(range(10)))
>>> [0, 2, 4, 6, 8]
you can use the filter built-in
def print_even_numbers(lst):
return list(filter(lambda x: not x%2, lst))
Note: on python 2 filter returns a list already so there is no need to convert it
def print_even_numbers(lst):
return filter(lambda x: not x%2, lst)
By the way, the function is named print_even_numbers but it does not print anything ;)
Related
Let's assume I'm creating a simple class to work similar to a C-style struct, to just hold data elements. I'm trying to figure out how to search a list of objects for objects with an attribute equaling a certain value. Below is a trivial example to illustrate what I'm trying to do.
For instance:
class Data:
pass
myList = []
for i in range(20):
data = Data()
data.n = i
data.n_squared = i * i
myList.append(data)
How would I go about searching the myList list to determine if it contains an element with n == 5?
I've been Googling and searching the Python docs, and I think I might be able to do this with a list comprehension, but I'm not sure. I might add that I'm having to use Python 2.4.3 by the way, so any new gee-whiz 2.6 or 3.x features aren't available to me.
You can get a list of all matching elements with a list comprehension:
[x for x in myList if x.n == 30] # list of all elements with .n==30
If you simply want to determine if the list contains any element that matches and do it (relatively) efficiently, you can do
def contains(list, filter):
for x in list:
if filter(x):
return True
return False
if contains(myList, lambda x: x.n == 3) # True if any element has .n==3
# do stuff
Simple, Elegant, and Powerful:
A generator expression in conjuction with a builtin… (python 2.5+)
any(x for x in mylist if x.n == 10)
Uses the Python any() builtin, which is defined as follows:
any(iterable) ->
Return True if any element of the iterable is true. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
Just for completeness, let's not forget the Simplest Thing That Could Possibly Work:
for i in list:
if i.n == 5:
# do something with it
print "YAY! Found one!"
[x for x in myList if x.n == 30] # list of all matches
[x.n_squared for x in myList if x.n == 30] # property of matches
any(x.n == 30 for x in myList) # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30] # indices of all matches
def first(iterable, default=None):
for item in iterable:
return item
return default
first(x for x in myList if x.n == 30) # the first match, if any
filter(lambda x: x.n == 5, myList)
You can use in to look for an item in a collection, and a list comprehension to extract the field you are interested in. This (works for lists, sets, tuples, and anything that defines __contains__ or __getitem__).
if 5 in [data.n for data in myList]:
print "Found it"
See also:
Contains Method
In operation
Another way you could do it is using the next() function.
matched_obj = next(x for x in list if x.n == 10)
You should add a __eq__ and a __hash__ method to your Data class, it could check if the __dict__ attributes are equal (same properties) and then if their values are equal, too.
If you did that, you can use
test = Data()
test.n = 5
found = test in myList
The in keyword checks if test is in myList.
If you only want to a a n property in Data you could use:
class Data(object):
__slots__ = ['n']
def __init__(self, n):
self.n = n
def __eq__(self, other):
if not isinstance(other, Data):
return False
if self.n != other.n:
return False
return True
def __hash__(self):
return self.n
myList = [ Data(1), Data(2), Data(3) ]
Data(2) in myList #==> True
Data(5) in myList #==> False
Consider using a dictionary:
myDict = {}
for i in range(20):
myDict[i] = i * i
print(5 in myDict)
Use the following list comprehension in combination with the index method:
data_n = 30
j = [data.n for data in mylist].index(data_n)
print(mylist[j].data.n == data_n)
I have to do a RECURSIVE FUNCTION, comparing two lists and returning the elements that they don't have in common.
This is what I have so far:
def compare(list1, list2):
if list2[0] in list1:
list1.remove(list2[0])
return compare(list1[1:], list2[1:])
return list1
#Example
>>>>compare([2, 3, 4, 5], [2, 3])
[4, 5]
I can compare if the first element of the list (list[0]) is the same but I am having trouble on how to compare the elements if they are not in the first position...I've tried many options but I'm a begginer in programming and don't really know how to do it. It must be a RECURSIVE FUNCTION, I can't use FOR or WHILE. And is there any way that I can do it without using remove()? Thank you so much
Here's an alternative answer. It has less duplication at the cost of a dirty trick to stay within the rules of the exercise:
def compare(a, b):
if isinstance(b, list):
# Let's cheat and change the meaning of the parameters.
return compare(a, set(b)) + compare(b, set(a))
else:
result = []
if a:
if a[0] not in b:
result.append(a[0])
result.extend(compare(a[1:], b))
return result
In your code you removed the first element from the list before calling the same function again. That's not necessary when you use recursion, it deals with that in a different way. In recursion you often don't modify a sequence in place, you pass a subsection to the inner call. To that inner call that subsection is the entire sequence.
How about this:
def compare(a, b, original_a = None, original_b = None):
result = []
if original_a is None:
original_a = a
if original_b is None:
original_b = b
if a and a[0] not in original_b:
result.append(a[0])
if b and b[0] not in original_a:
result.append(b[0])
if a or b:
result += compare(a[1:], b[1:], original_a, original_b)
return result
Start with a for loop (it's easier to think about):
def disjunctive_union(a, b):
a_filt = [x for x in a if x not in b]
b_filt = [x for x in b if x not in a]
return a_filt + b_filt
Let's make this "recursive". One idea is to remove elements we've already checked and call our function on a smaller list.
def disjunctive_union(a, b):
if len(a) == 0:
return b
first = a[0]
if first not in b:
return [first] + disjunctive_union(a[1:], b)
# These filters can individually be made recursive too
# (and often are in functional languages!)
a = [x for x in a if x != first]
b = [x for x in b if x != first]
return disjunctive_union(a, b)
EDIT: To demonstrate a recursive variant of the filters:
a = [x for x in a if x != first]
can be replaced with:
def recursive_filter(pred, xs):
x = next(xs)
if pred(x):
yield x
yield from recursive_filter(pred, xs)
a = list(recursive_filter(lambda x: x != first, iter(a)))
EDIT 2: I thought about it a bunch and here's a simpler solution:
def disjunctive_union(a, b):
a_filt = list(recursive_filter(lambda x: x not in b, iter(a)))
b_filt = list(recursive_filter(lambda x: x not in a, iter(b)))
return a_filt + b_filt
...using the recursive_filter I defined above.
(FWIW, I think this whole thing is kind of a pointless exercise in making a non-recursive function recursive...)
Hi here is one more solution.
def diff(l1,l2):
result=[]
if len(l1)==0:
#return l2, finally it will only contain unique elements (if any)
return l2
if l1[0] in l2:
copy=l1[0]
#remove all occurances of the common element from both lists
l1=list(filter(lambda a: a != l1[0], l1))
l2=list(filter(lambda a: a != copy, l2))
else:
#if list1's first element is not in list2 add it to result and pop it
result.append(l1[0])
l1.pop(0)
result+=diff(l1,l2)
return result
list1=[1,3,2,4,4,5]
list2=[1,2,7]
print(diff(list1,list2))
Output:
[3, 4, 4, 5, 7]
Trying to return all odd numbers from a nested list using recursion. Not too sure what I am doing wrong here.
def return_odds(a):
odd = []
if isinstance(a, list):
for item in a:
if isinstance(item, list):
return_odds(item)
if isinstance(item, int):
if item % 2 == 1:
odd.append(item)
if isinstance(a, int):
if a % 2 == 1:
odd.append(a)
return odd
You're dropping the returned value from your recursion.
A typical recursive function looks something like this:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
In your example, when you recurse and call return_odds(item), your not using the returned value. Try this instead:
def return_odds(a):
odd = []
if isinstance(a, list):
for item in a:
if isinstance(item, list):
odd += return_odds(item)
if isinstance(item, int):
if item % 2 == 1:
even_list.append(item)
if isinstance(a, int):
if a % 2 == 1:
odd.append(a)
return odd
Note that the return value of return_odds(item) is appended to your odd list.
There are two errors in your code.
Your errors
First you throw away the return value of your recursive call. Instead, extend your list odd with the returned value.
return_odds(item)
# replace by: odd.extend(return_odds(item))
Second, you have a variable even_list that appears nowhere. You probably meant to use the existing list odd.
even_list.append(item)
# replace by: odd.append(item)
Improvement
That being said, there is still a conceptual error in your code: *it will accept a single int and return it in a list*. This does not seem to be part of your requirements. Instead, loop though your input a and do a recursive call when encoutering a list.
def return_odds(a):
odd_numbers = []
for i in a:
if isinstance(i, list):
odd_numbers.extend(return_odds(i))
elif isinstance(i, int) and i % 2:
odd_numbers.append(i)
# You might also want to determine the behaviour if i is not an int
return odd_numbers
Example
print(return_odds([1, 2, 3, [4, 5, 6, [7, 8, 9]]]))
Output
[1, 3, 5, 7, 9]
I have a function
def process_list(mylist):
return [x for x in mylist if isinstance(x, int)];
I need to modify this function so that in the new list that is returned, every integer divisible by 3 is replaced by -1, every integer divisible by 5 is replaced by -2, and every integer divisible by both is replaced by -3. Other integers are left unchanged. As before non-integers should be dropped.
Thus, process_list([1, 3, 5, 15, 22, 'b']) should return [1, -1, -2, -3, 22].
I can do this by using if-else. But I want to know the pythonic way of doing it.
Well, pythonic for me is not a synonym for one-liner.
See this.
Because flat is better than nested and sparse is better than dense
def process_list(mylist):
# filter, prefer generator expression
tmp = (x for x in mylist if isinstance(x, int))
# mapping logic
mappings = ((15, -3), (5, -2), (3, -1))
def fizzbuzz(num):
try:
return next(v for k, v in mappings if num%k == 0)
except StopIteration:
return num
# return a mapped list
return map(fizzbuzz, tmp)
You can change the function like this.
def process_list(mylist):
return [(-3 if x % 15 == 0 else (-2 if x % 5 == 0 else ( -1 if x % 3 == 0 else x))) for x in mylist if isinstance(x, int)]
I cannot say that this is the best way, but as someone that is not fond of long if .. else chains, I would rewrite Hannes Ovrén's filter as
def convert_ints(x, dividers=(15, 5 ,3)):
for val, div in enumerate(dividers):
if (x%div)==0:
return -len(dividers)+val
return x
This is scalbale solution, that may be easily expanded
EDIT:
for more complicated cases, a tuple of lamdba-s may be used:
conditions=(lambda x:x%15==0, lambda x:x%5==0, lambda x:x%3==0)
I think the pythonic way is to use if-else in this case.
For example
def process_list(mylist):
return list_filter(x) for x in mylist if isinstance(x, int)]
def list_filter(x):
if x % 3 == 0:
return -1
elif ... # <snip>
(even though I'd probably rewrite the process_list function as a for loop that builds a new list)
Using list comprehension will most likely just be a lot harder to read, and/or require multiple passes.
Let's assume I'm creating a simple class to work similar to a C-style struct, to just hold data elements. I'm trying to figure out how to search a list of objects for objects with an attribute equaling a certain value. Below is a trivial example to illustrate what I'm trying to do.
For instance:
class Data:
pass
myList = []
for i in range(20):
data = Data()
data.n = i
data.n_squared = i * i
myList.append(data)
How would I go about searching the myList list to determine if it contains an element with n == 5?
I've been Googling and searching the Python docs, and I think I might be able to do this with a list comprehension, but I'm not sure. I might add that I'm having to use Python 2.4.3 by the way, so any new gee-whiz 2.6 or 3.x features aren't available to me.
You can get a list of all matching elements with a list comprehension:
[x for x in myList if x.n == 30] # list of all elements with .n==30
If you simply want to determine if the list contains any element that matches and do it (relatively) efficiently, you can do
def contains(list, filter):
for x in list:
if filter(x):
return True
return False
if contains(myList, lambda x: x.n == 3) # True if any element has .n==3
# do stuff
Simple, Elegant, and Powerful:
A generator expression in conjuction with a builtin… (python 2.5+)
any(x for x in mylist if x.n == 10)
Uses the Python any() builtin, which is defined as follows:
any(iterable) ->
Return True if any element of the iterable is true. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
Just for completeness, let's not forget the Simplest Thing That Could Possibly Work:
for i in list:
if i.n == 5:
# do something with it
print "YAY! Found one!"
[x for x in myList if x.n == 30] # list of all matches
[x.n_squared for x in myList if x.n == 30] # property of matches
any(x.n == 30 for x in myList) # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30] # indices of all matches
def first(iterable, default=None):
for item in iterable:
return item
return default
first(x for x in myList if x.n == 30) # the first match, if any
filter(lambda x: x.n == 5, myList)
You can use in to look for an item in a collection, and a list comprehension to extract the field you are interested in. This (works for lists, sets, tuples, and anything that defines __contains__ or __getitem__).
if 5 in [data.n for data in myList]:
print "Found it"
See also:
Contains Method
In operation
Another way you could do it is using the next() function.
matched_obj = next(x for x in list if x.n == 10)
You should add a __eq__ and a __hash__ method to your Data class, it could check if the __dict__ attributes are equal (same properties) and then if their values are equal, too.
If you did that, you can use
test = Data()
test.n = 5
found = test in myList
The in keyword checks if test is in myList.
If you only want to a a n property in Data you could use:
class Data(object):
__slots__ = ['n']
def __init__(self, n):
self.n = n
def __eq__(self, other):
if not isinstance(other, Data):
return False
if self.n != other.n:
return False
return True
def __hash__(self):
return self.n
myList = [ Data(1), Data(2), Data(3) ]
Data(2) in myList #==> True
Data(5) in myList #==> False
Consider using a dictionary:
myDict = {}
for i in range(20):
myDict[i] = i * i
print(5 in myDict)
Use the following list comprehension in combination with the index method:
data_n = 30
j = [data.n for data in mylist].index(data_n)
print(mylist[j].data.n == data_n)