Algorithm similar to 'Fizzbuzz' - python

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.

Related

Printing out only odd values in a list in Python

I'm just starting out in Python and I can't seem to work this practice question out.
Write a function that takes in a collection and returns a list of elements of all values that are odd. You should ignore any non-numeric elements in the collection.
Required Signature: def odd_numbers1(x):
for example, calling odd_numbers1([1,2,3,3,'3']) will return [1,3,3]
for example, calling odd_numbers1([False,True,3,5.0,7.5]) will return [True,3, 5.0]
This is what I have so far but I hit an error when I reach '3'.
for i in x:
if x %2 == 0 or type(x) != int:
None
else:
print(x)
x = [1,2,3,3,'3']
odd_numbers1([1,2,3,3,'3'])```
if x %2 == 0 or type(x) != int will be evaluated from left to right. If you have a string, '3', then it will check the modulus before checking if the type is int. You should reverse the order of checking and can also use isinstance: if not isinstance(x, int) or x % 2 == 0.
This will work because of short circuit evaluation.
#chrispresso is exactly right, your checking the modulus before you know if its an int so you need to reverse that logic. Personally I would change the if statement to say. If it is an int, and its not divisable by two then print. That to me looks cleaner and there is no need for an else part
def odd_numbers1(x):
for i in x:
if isinstance(i, int) and i % 2 != 0:
print(i)
odd_numbers1([1, 2, 3, 3, '3'])
OUTPUT
1
3
3
The question speaks of functions and returns, so just printing out the list might not be a correct answer. In addition to #Chrispresso's answer, the simplest way would be something like so:
def odd_numbers1(x):
retval = []
for i in x:
if type(x) != int or x%2==0:
continue
else:
retval.append(x)
return retval
List comprehensions are a great feature of Python that could also really help you out here.

Filtering out odd numbers and squaring them in a tuple in Python

This is a question from a school assignment, and appreciate any assistance in pointing out my mistake.
First of all, with respect to the map() function in Python, I have been tasked (non-optionable) to redefine it as such to make it specific to a tuple:
def map(fn, seq):
if seq == ():
return ()
else:
return (fn(seq[0]),) + map(fn, seq[1:])
Using this, I am supposed to define another function square_odd(tuple) that takes in a tuple containing integers as an argument, and specifically square the terms only if they are odd. Essentially, for a tuple input of (5,6,7,8,9), I should be returned (25, 6, 49, 8, 81).
My idea is simply to utilise lambda to write a function, paired with an if to filter out the odd numbers. Here's what I have:
def square_odd(tpl):
return map(lambda x: x*x if x%2 == 0, tpl)
Python has returned me a SyntaxError at the comma before tpl. Can anyone point out what may be the issue with this? Must I write an else condition as well? I have tried adding else x but I am only returned the integer value of the first value.
That's because you should write else statement.
map(lambda x: x*x if x%2 == 1 else x, tp1)
and tried this code as simple. And also you should fixed x%2 == 0.
This condition will find even number.
return tuple(map(lambda x: x*x if x%2 == 1 else x, tp1))
if with lambda expects an else statement. So it should be like this:
def square_odd(tpl):
return map(lambda x: x if x%2 == 0 else x*x, tpl)
Which means, take x if x%2==0 i.e. if it is even, else take x*x which is it's square.
def map(fn, seq):
if seq == ():
return ()
else:
return (fn(seq[0]),) + map(fn, seq[1:])
def square_odd(tpl):
return map(lambda x: x**2 if x%2 else x, tpl)
t = (1,2,3,4,5)
print(square_odd(t))
I have done this and the output is (1, 2, 9, 4, 25).
PS the syntax error raise because the ternary operator A if condition else B cannot be used as A if condition

Recursive Function - Compare 2 lists, return the elements that don't exist in both

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]

Function to determine if adjacent elements are alike

I've been stuck on this for a while and I keep running into problems, I'm trying to create a function that returns true if at least one pair of adjacent elements in a list are equal.
Test cases:
[1, 2, 3] -> False
[1, 2, 2, 3] -> True
[2, 6, 3, 6] -> False
['a', 'b', 'c', 'd', 'd'] -> True
def equal_adjacent_elements(l):
for x in range(len(l)):
if l[x] == l[x+1] or l[x] == l[x-1]:
return True
else:
return False
The problems I run into are assertion errors and I believe it's because of my loop. Once I find a pair that is equal the returned value won't stay the same because my loops will evaluate the next values in the list. So I just need to find at least one pair, I don't know how I would do that though.
You can zip the list with itself offest by 1 and use any to short-cut the find-one pattern:
def equal_adjacent_elements(l):
return any(x == y for x, y in zip(l, l[1:]))
I made few changes. It should work now.
def equal_adjacent_elements(l):
for x in range(len(l)-1):
if l[x] == l[x+1]:
return True
return False
or, shorter one using any,
def equal_adjacent_elements(l)
return any( l[x] == l[x+1] for x in range(len(l)-1) )
There are two problems here:
the indices can run into overflow here;
you immediately return False from the moment there are two consecutive elements that are not equal, you should return False after the for loop.
The index problem here is that x ranges from 0 to (excluding) len(l). So that means x-1 ranges from -1 (which is the last element of the list) to len(l)-1 and x+1 from 1 to len(l) (including). But the list is not that long, so you get an index out of the list bounds, which is an error.
A more Pythonic approach however is to use a zip(..) over the list l, and the "tail" of the list (the list omitting the first element). So zip(l, l[1:]).
We can iterate over every pair x,y of l and l[1:]. In case x == y, then we have such element and return True.
In case we fail to find such pair, we eventually return `False.
So a correct implementation is:
def equal_adjacent_elements(l):
for x,y in zip(l, l[1:]):
if x == y:
return True
return False
Python however has a builtin any, that will return True from the moment the iterable we give it contains at least one True; and False if no element has truthiness True.
So we can convert the above code to something using the any builtin:
def equal_adjacent_elements(l):
return any(x == y for x,y in zip(l, l[1:]))
I'm kinda new to python but anyways hoped this is easy enough
def equal_adjacent_elements(l):
try:
for i in range(0, len(l)):
if l[i] == l[i+1]:
return True
except IndexError:
return False

Function Definition: Printing a list of even integers

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 ;)

Categories

Resources