Alternate through lambda functions - python

I have to make a function that takes a list and and maps two lambda functions alternatively. Like this:
>>> alternateMap(lambda x: x+1, lambda y: y+10, [1, 2, 3, 4])
[2, 12, 4, 14]
So, the first function lambda x: x+1 applies to the first element and the third element, the second function lambda y: y+10 applies to the second and fourth elements.
So far I have this:
def alternateMap(function1, function2, l):
for i in l:
a = map(function1, l)
i += 2
for n in l[1:]:
a = map(function2, l)
i += 2
return a
But unfortunately it's not correct.

This works for any number of functions.
>>> from itertools import cycle
>>> func_cycle = cycle([lambda x:x+1, lambda y:y+10])
>>> [next(func_cycle)(item) for item in [1, 2, 3, 4]]
[2, 12, 4, 14]
You stated in comments elsewhere that you need a version that uses map. Here you go:
import itertools
class callable_cycle(itertools.cycle):
def __call__(self, *args, **kwds):
return next(self)(*args, **kwds)
func_cycle = callable_cycle([lambda x:x+1, lambda y:y+10])
map(func_cycle, [1, 2, 3, 4])

Related

How do I write instructions inside map in Python?

The input is a list: ["asdf", "ghjk", "lmnop", "zyx"].
I specifically need to apply a function over all elements of the list (so, I should use map). The function should do something like f(x, k) = x + k, where k is a constant equal to 1, and x is a counter (hence, x will be 0 at first, and when gradually iterating over the list, it should increment somehow, but how?).
Assuming these, the expected output should be: [1, 2, 3, 4].
from functools import partial
def f(x, k):
return x + k
def with_partial(my_list, k=1):
func = partial(f, k=k) # partial object which acts as a function when called
x = 0 # counter
# map -> applies a funciton over all elements of my_list
rez = list(map(lambda it: (func(x)), my_list))
# if I want to increment it, it should look like: rez = list(map(lambda it: x = (func(x)), my_list))
print("Result with partial: " + str(rez))
if __name__ == "__main__":
with_partial([5, 6, 7])
with_partial(["asdf", "ghjk", "lmnop", "zyx"])
But the output is:
Result with partial: [1, 1, 1]
Result with partial: [1, 1, 1, 1]
But I want it to be like:
Result with partial: [1, 2, 3]
Result with partial: [1, 2, 3, 4]
I can use list comprehension quite easily for that type of problem, but I need to understand how can I write instructions inside map, so that I can increment my counter effectively. Or... Is there anything about partial function I should know already, but I don't? How do I solve this type of problem using functional programming?

How to add an array with using Python

Given an array a = [1,2,3,[4,5]] using Python 3, how can I add all the elements in the array?
sum(a[0])
sun(a[0][1])
The above code did not work. Also in the case, if you're given an array with an unknown amount of arrays inside arrays, How can those numbers be calculated?
def xsum(x):
if not x:
return 0
head, *tail = x
if isinstance(head, list):
return xsum(head) + xsum(tail)
elif tail:
return head + xsum(tail)
else:
return head
You need a flatten function. Here is one:
def flatten(a):
"""generator of flattened n-deep iterable (excluding str) a."""
for elem in a:
if not isinstance(elem, str):
try:
yield from flatten(elem)
except TypeError:
yield elem
else:
yield elem
which you can then use in sum, for example:
a = [1, 2, 3, [4, [5, 6]]
print(list(flatten(a))) # --> [1, 2, 3, 4, 5, 6]
print(sum(flatten(a))) # --> 21
You can use functools.reduce to sum this nested list
>>> from functools import reduce
>>> a = [1,2,3,[4,5]]
>>> reduce(lambda x,y: x + (sum(y) if type(y)==list else y), [0]+a)
15
If the list can be more than one level nested, you have to use a recursive approach
>>> f = lambda x,y: x + (reduce(f, y) if type(y)==list else y)
>>> reduce(f, [0]+a)
15
You can use the closure property for finding sum of infinite nested list.
def nested_list_sum(x):
c = []
def l_sum(x):
for i in x:
if isinstance(i, list):
l_sum(i)
else:
c.append(i)
l_sum(x)
return sum(c)
like
a = [1,2,3,[4,5]] ----> 15
a = [1,2,3,[4,5, [6,7, [8, 9]]], [10, 11, 12, [13, 14, 5]]] -- > 110

function to extend a list

How can I create a function that can take any list and extend it. Here is what I am talkig about:
def list(l, p):
return l.extend(p)
I also want to have p to be of any nature.
Please don't override the keywords, here I post an answer based on my understanding of your question, which is not very clear.
def my_list(l, *args):
from itertools import chain
sub_lists = filter(lambda x: isinstance(x, list), args)
elements = filter(lambda x: not isinstance(x, list), args)
l.extend(list(chain.from_iterable(sub_lists)))
l.extend(list(elements))
return l
l1 = [1, 2]
l2 = [3, 4]
l3 = [5, 6]
e = 7
new_list = my_list(l1, l2, l3, e, 8)
# [1, 2, 3, 4, 5, 6, 7, 8]
print(new_list)

Replacing element in list without list comprehension, slicing or using [ ]s

I'm taking this online Python course and they do not like the students using one-line solutions. The course will not accept brackets for this solution.
I already solved the problem using list comprehension, but the course rejected my answer.
The problem reads:
Using index and other list methods, write a function replace(list, X, Y) which replaces all occurrences of X in list with Y. For example, if L = [3, 1, 4, 1, 5, 9] then replace(L, 1, 7) would change the contents of L to [3, 7, 4, 7, 5, 9]. To make this exercise a challenge, you are not allowed to use [].
Note: you don't need to use return.
This is what I have so far, but it breaks because of TypeError: 'int' object is not iterable.
list = [3, 1, 4, 1, 5, 9]
def replace(list, X, Y):
while X in list:
for i,v in range(len(list)):
if v==1:
list.remove(1)
list.insert(i, 7)
replace(list, 1, 7)
This was my original answer, but it was rejected.
list = [3, 1, 4, 1, 5, 9]
def replace(list, X, Y):
print([Y if v == X else v for v in list])
replace(list, 1, 7)
Any ideas on how to fix my longer solution?
range() returns a flat list of integers, so you can't unpack it into two arguments. Use enumerate to get index and value tuples:
def replace(l, X, Y):
for i,v in enumerate(l):
if v == X:
l.pop(i)
l.insert(i, Y)
l = [3, 1, 4, 1, 5, 9]
replace(l, 1, 7)
If you're not allowed to use enumerate, use a plain old counter:
def replace(l, X, Y):
i = 0
for v in l:
if v == X:
l.pop(i)
l.insert(i, Y)
i += 1
l = [3, 1, 4, 1, 5, 9]
replace(list, 1, 7)
Finally, you could use what the authors of the question were probably looking for (even though this is the most inefficient approach, since it linear searches through the list on every iteration):
def replace(l, X, Y):
for v in l:
i = l.index(v)
if v == X:
l.pop(i)
l.insert(i, Y)
l = [3, 1, 4, 1, 5, 9]
replace(l, 1, 7)
You can also try this (not using []s or enumerate(), as required):
for i in range(len(l)): # loop over indices
if l.__index__(i) == X: # i.e. l[i] == X
l.__setitem__(i, Y) # i.e. l[i] = Y
This probably isn't what the assignment wants you to do, but I'll leave it here for learning purposes.
Note: You shouldn't use list as a variable name since that's already used by a built-in function. I've used l here instead.
If enumerate is not allowed, you can also use a while loop.
>>> def replace(L_in, old_v, new_v):
while old_v in L_in:
idx=L_in.index(old_v)
L_in.pop(idx)
L_in.insert(idx, new_v)
>>> L = [3, 1, 4, 1, 5, 9]
>>> replace(L, 1, 7)
>>> L
[3, 7, 4, 7, 5, 9]
Do not use list as a name, it will cause you much pain.
def replace(my_list, X, Y):
while X in my_list:
my_list.insert(my_list.index(X), Y)
my_list.pop(my_list.index(X))
This worked for me. Pretty straight forward. Probably a way of doing it with less lines, but based on what has been taught on the website so far, this works.
def replace(L, X, Y):
while X in L:
i = L.index(X)
L.insert(i, Y)
L.remove(X)
totally agree with Asad Saeeduddin
but, 1st value of i must be -1, it will help replace the 1st object in list in need
def replace(l, X, Y):
i = -1
for v in l:
i += 1
if v == X:
l.pop(i) # remove item at given position (position number i)
l.insert(i, Y) # insert item Y at position i
l = [1, 1, 4, 1, 5, 9]
replace(l, 1, 7)
print(l)

How to pass one argument from list and another argument in the built-in function map() in Python?

In Python, one could apply a function foo() to every element of a list by using the built-in function map() as follows:
def foo(x):
return x*x
print map(foo, [1, 2, 3, 4])
This would print as one could guess: 1 4 9 16.
Lets say the function foo() now accepts two arguments instead of one, and is defined as follows:
def foo(x, y):
return x+y
In this case, x is an element of the list, and y is some number which is the same for the whole list. How can we use map() in this case such that foo() is applied on every element of the list, while taking another argument y which is the same for every element?
I would like to be able to do something like:
print map(foo(:, 5), [1, 2, 3, 4])
which should give me: 6 7 8 9.
Is it possible in Python? There could be alternatives for this particular example of adding 'y' to all the elements. But I am looking for an answer that would use map().
You can use a lambda function. This is treated just like a normal function, with the x value being the parameter for your iterator, and the return value being x+5 in this case.
>>> def foo(x, y)
... return x + y
...
>>> l = [1, 2, 3, 4]
>>> map(lambda x: foo(x, 5), l)
[6, 7, 8, 9]
For the record, #PaoloMoretti had this in before me :)
One way to do this is with functools.partial:
>>> from functools import partial
>>> def foo(x, y):
... return x + y
...
>>> l = [1, 2, 3, 4]
>>> map(partial(foo, y=2), l)
[3, 4, 5, 6]
>>>
Another way is to change the way you define the function:
>>> def foo(y):
... def inner(x):
... return x + y
... return inner
...
>>> map(foo(2), l)
[3, 4, 5, 6]
>>>
Incidentally, using lambda would be the most straightforward way to do this, as Paolo Moretti said. Any particular reason why you have to use map() the way you described?

Categories