Reduce with enumerate Python - python

I'm trying to get product of list where every element is multiplied by its index + 1. I tried with reduce and enumerate
value = reduce(lambda a, b: (a[0]+1)*a[1]*b[1], enumerate(list))
but it gives TypeError: 'int' object is not subscriptable.
Is it possible to do it in one line?
Editv2
example of list [1,2,3]
desire output list[0]*1 * list[1]*2 * list[2]*3 = 36

Simplest:
lst = [1,2,3] # do not shadow `list`
sum(i*v for i, v in enumerate(lst, 1))
# 14
Your reduce approach fails as it returns an int which is not the same type that it expects as its two inputs (tuple). You could do it with:
reduce(lambda a, b: (a[0]*a[1] + b[0]*b[1], 1), enumerate(lst, 1))[0]
# 14
Note the (..., 1) structure of the lambda expression where the 1 serves as an auxiliary factor for the next step.
Update: As you actually want the homogenous product of all the elements of your nested iterable, the following is simpler:
from itertools import chain
from operator import mul
reduce(mul, chain(*enumerate(lst, 1)))
# 36

The trick is to make a new list and multiply through it.
Create a new list where a number at index i is i*list[i], indexing starting with 1:
>>> new_list = [a*b for a, b in enumerate(list, 1)]
>>> new_list
[1, 4, 9]
and multiply over your new list:
>>> reduce((lambda x, y: x*y), new_list)
36
In one line:
>>> reduce((lambda x, y: x*y), [a*b for a, b in enumerate(list, 1)])
36
Hope it helped :)
Note: Answer edited to meet OP's changes.

ans = sum(i * x for i, x in enumerate(list, 1))
Not exactly what you are asking for, but it gives the desired result.

Related

Basic Python manipulation of nested list

For the following nested list, Lst, I need to keep the first inner list, square the second, and cube the last one.
Lst = [[1,2,3],[2,3,4],[3,4,5]]
My current code is squaring all the nested list in the Lst.
list(map(lambda lst: list(map(lambda x: x**2, lst)), Lst))
How can I fix this? I just started learning Python.
Since you're not doing the same operation on each nested list, you shouldn't use map() for the top-level list. Just make a list of results of different mappings for each.
[Lst[0], list(map(lambda x: x**2, lst[1])), list(map(lambda x: x**3, lst[2]))]
However, there's an obvious pattern to this, so you can generalize it using enumerate() and a list comprehension:
[list(map(lambda x: x**i, sublist)) for i, sublist in enumerate(Lst, 1)]
[list(map(lambda x: x**i, l)) for i,l in enumerate(Lst, 1)]
[[1, 2, 3], [4, 9, 16], [27, 64, 125]]
Your processing obviously needs to take into account where in the list you are. Forcing this into a one-liner makes it more dense than it really needs to be, but see if you can follow along with pencil and paper.
[[x if i == 0 else x**2 if i == 1 else x**3 for x in Lst[i]] for i in range(3)]
Demo: https://ideone.com/o8y0ta
... Or, as cleverly suggested in Barmar's answer,
[[x**i for x in Lst[i]] for i in range(3)]
Try indexing the outer list and then call the map function on each index
def square(number) :
return number ** 2
def cube(number) :
return number ** 3
lst = [[1,2,3],[2,3,4],[3,4,5]]
lst[0] = lst[0]
lst[1] = list(map(square, lst[1]))
lst[2] = list(map(cube, lst[2]))
print(lst)

Pair two lists in inverse order

What I want to do is to choose one item in list A and another one in list B, pair them like:
A[0]+B[n], A[1]+B[n-1],.....,A[n]+B[1]
I use two for loops but it doesn't work:
class Solution(object):
def plusOne(self, digits):
sum=0
for j in range(len(digits)-1,0,-1) :
for i in range(0,len(digits),1):
sum=sum+digits[i]*pow(10,j)
return sum+1
I inputted [1,2,3] and what I want to get is 124,
but I got 661.
Edit:
Sorry, the example I gave above is not so clear.
Let us think about A[1,2,3] and B[6,5,4].
I want output [5,7,9], because 5 is 1+4, 7 is 2+5, 9 is 3+6
What you are trying to do is turn a list of digits into the according number (and add 1). You can enumerate the reversed list in order to pair a digit with its appropriate power of 10:
digits = [1, 2, 3]
sum(10**i * y for i, y in enumerate(digits[::-1])) + 1
# 124
You can apply that to your other example as follows, using zip:
A = [1,2,3]
B = [6,5,4]
sum(10**i * (x+y) for i, (x, y) in enumerate(zip(B, A[::-1])))
# 579
You can do this without a loop:
A = [1,2,3]
B = [6,5,4]
C = list(map(sum,zip(A,B[::-1]) ))
print(C)
zip() - creates pairs of all elements of iterables, you feed it A and B reversed (via slicing). Then you sum up each pair and create a list from those sums.
map( function, iterable) - applies the function to each element of the iterable
zip() works when both list have the same length, else you would need to leverage itertools.zip_longest() with a defaultvalue of 0.
K = [1,2,3,4,5,6]
P = list(map(sum, zip_longest(K,C,fillvalue=0)))
print(P)
Output:
[5, 7, 9] # zip of 2 same length lists A and B reversed
[6, 9, 12, 4, 5, 6] # ziplongest for no matter what length lists
You only need one loop if you want to search in same list back and forth or different list with same length (i and len(lst)-1-i).
Try not use build-ins such as sum, list, tuple, str, int as variable names, it will give you some nasty result in some case.
class Solution(object):
def plusOne(self, digits):
sum_val = 0
for i in range(len(digits)):
sum_val += digits[i]*pow(10, len(digits)-1-i)
return sum_val+1
sol = Solution()
dig = [1, 2, 3]
print(sol.plusOne(dig))
Output:
124
for A = [1, 2, 3] and B = [6, 5, 4].
You can use a list comprehension:
res = [A[i]+B[len(A)-i-1] for i in range(len(A))]
Or the zip() function and a list comprehension:
res = [a+b for (a, b) in zip(A, reversed(B))]
Result:
[5, 7, 9]

Condition (a*a + b*b = c*c) satisfies in a list using python

I need to know whether the elements in the list satisfies the condition
a*a + b*b = c*c, where a, b and c are any elements in the following list:
original_list =[8,5,73,3,34,4,23,73]
Mathematically, 3*3 + 4*4 = 5*5, but not sure how to traverse the list in python to satisfy that condition.
You can iterate over the items from your list using itertools.combinations:
import itertools
for a, b, c in itertools.combinations(sorted(original_list), 3):
if a*a + b*b == c*c:
print("Pythagorean triple found:", a, b, c) # or whaver...
Note that I sort the original list before passing it to combinations. That ensures that a <= b <= c. While we don't really care about the relative order of a and b, but the fact that c is no smaller than either of them is a prerequisite for the test you're doing.
This questions revolves more around math and algorithms than pythonisms. The solution I propose below has a complexity in O(n**2).
The idea is to reverse the function (x, y) => x * x + y * y, where the search space is the cross product of the original list with itself. Then, using Python set operators, compute the intersection between the application image and the acceptable squares. Eventually, use the reversed application to reconstruct the triplets.
from collections import defaultdict
original_list = [8, 5, 73, 3, 34, 4, 23, 73]
uniq = sorted(set(original_list))
antecedents = defaultdict(lambda: []) # Reverse mapping
for i, left in enumerate(uniq):
for right in uniq[i+1:]:
key = left * left + right * right
antecedents[key].append((left, right))
# The keys of antecedents are sum of squares
uniq_squares = set([ x * x for x in uniq ])
common_keys = uniq_squares & antecedents.keys()
for key in common_keys:
sqrt = int(0.5 + key**0.5)
key_antecedents = antecedents[key]
for (left, right) in key_antecedents:
print("Found triplet:", (left, right, sqrt))
Python code
[(a,b,c) for a in original_list for b in original_list for c in original_list if a*a+b*b==c*c]
Output:
[(3, 4, 5), (4, 3, 5)]

How to perform operation on elements of list which depend on previous elements?

Using map can do operations of current element in list:
l = [1,2,3,4,5,6];
print(list(map(lambda x: x*2, l)))
# gives [2, 4, 6, 8, 10, 12]
In above, multiply by 2 is done for all elements in l. But how to mulitiply by 2 an element in l, only if previous value in l is odd? Can use map for this?
For example to get:
[1,4,3,8,5,12] % only 2, 4 and 6 from l are multiplyied by 2, because before them there are odd numbers 1,3,5.
You can use map if you do it on an enumerated version:
print(list(map(lambda index,x: x*2 if index > 1 and l[index-1] & 1 else x, enumerate(l))))
However, as you might have noticed, that's really not very readable. It's better to just use a list comprehension or a for loop:
print([x*2 if index > 1 and l[index-1] & 1 else x
for index, x in enumerate(l)])
You can use zip in combination with map:
print(l[:1] + list(map(lambda x: x[1]*2 if x[0] & 1 else x[1], zip(l, l[1:]))))
Note that I had to explicitly prepend the first element of the list because it has no previous element to test.
You can zip the list along with a sliced copy of the list to pair all of the items:
>>> l = [1, 2, 3, 4, 5, 6]
>>> zip(l, l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
You can use something callable to track your previous value. Depending on how abstract you want this:
prev = [0]
def callback(x):
val = ((prev[0] % 2) + 1) * x
prev[0] = x
return val
print list(map(callback, l))
I realise that it was probably just a trivial example, but thought it worth mentioning that in your example case the condition "if the previous value is odd" is the same as "if the current value is even" (at least for your sample input). In which case I would just use
print([x if x&1 else x*2 for x in l])
For the more general case and assuming the condition may be more complex than just "previous item is odd", I would take a few lines to express the solution clearly. Python's generators are a good fit:
>>> def double_if_prev_odd(l):
... prev_odd = False # initial condition for 1st element
... for x in l:
... yield x**2 if prev_odd else x
... prev_odd = x&1
...
>>> list(double_if_prev_odd(l))
[1, 4, 3, 16, 5, 36]

python list comprehension unzipping multiple returns

anyone have any idea how to unpack the values in a tuple for a list comprehension?
So a practical example:
def func(x,y):
return x*2, y*2
x = [1, 2, 3]; y = [1, 2, 3]
a, b = [ func(i,j) for i, j in zip(x,y) ]
Unfortunately, that gives me an error sayin' there are too many values to unpack...
I've tried
zip(*func(i,j))
(a,b) = ...
Do you mean the following?:
a, b = zip(*[func(i,j) for i, j in zip(x,y)])
for x1,y1 in [func(i,j) for i, j in zip(x,y)]:
# do something with x1,y1
The problem is that the list comprehension returns something like
[(1,1), (4,4), (6,6),..]
so the list contains more than just two elements.
I don't see why you can't just do:
a = [i*2 for i in x]
b = [i*2 for i in y]
If you are worried about duplicate code, create a function:
def func(l):
return [i*2 for i in l]
a, b = func(x), func(y)
Trying to pack everything in one line, using fancy list unpacking etc., does not necessarily increase readability.

Categories

Resources