How can we take out the product of elements? - python

I have the list named as input_list = [1, 2, 3, 4, 5] , I want to take the product of every elements except the specific index which is running at the moment.
Example
input_list1 = [1, 2, 3, 4, 5]
If I say that in the first index the value is 1 , in the output list, its product will be the all elements except first index (5*4*3*2) and insert it into new list, same goes for all elements.
Expected_Output:
prod = [120, 60, 40, 30, 24]

You can use math.prod for the task:
import math
out = [
math.prod(input_list1[:i] + input_list1[i + 1 :])
for i in range(len(input_list1))
]
print(out)
Prints:
[120, 60, 40, 30, 24]

Let's find the product of all the numbers in the list first.
from functools import reduce
from operator import mul
l = [1, 2, 3, 4, 5]
product = reduce(mul, l, 1)
Once we have it, let's iterate over all items in the list and divide the product by that item. This will give us the product of all the items except that one.
ans = [product // num for num in l]
Time Complexity: O(n)

This should work:
Code:
import math
input_list1 = [1, 2, 3, 4, 5]
def main(l):
final = []
for i in l:
b = lambda a: int(a) if a == int(a) else a
final.append(b(math.prod(input_list1) / int(i)))
return final
prod = main(input_list1)
print(prod)
Output:
[120, 60, 40, 30, 24]
This should work.

Related

Use different list values in order to do the same sum with each

Please help, I need to have a moving value in my code based upon a list!
I have a list, the list is as follows:
my_list = [1, 2, 2, 3, 5, 6, 7, 7, 9, 10]
I have a part of my code which uses this list in order to do a sum, this is as follows:
val = my_list[0]+1
ans = val*9
What I want is to have val be replaced by each of the numbers in my_list i.e. the first time it would be 1x9 and then the next 2x9. However, I cannot find anywhere how to do this.
val = my_list[x]
val += 1
ans = val * 9
x += 1
this way you can just run your code, then add 1 to x
move the x += 1 line to whereever you want
Is your ans a list?
Do "(x+1)*9" for each elements?
ans = [(x+1)*9 for x in my_list]
What you want is vectorization - for which you can use the numpy package:
import numpy as np
my_list = [1, 2, 2, 3, 5, 6, 7, 7, 9, 10]
my_np_list = np.array(my_list)
ans = 9 * my_np_list
# vectorization applies to each element of my_np_list in parallel
# the `9 *` calculation.
## ans contains:
## array([ 9, 18, 18, 27, 45, 54, 63, 63, 81, 90])
## you can sum accross ans by the .sum() method
ans.sum() ## 468
It is as if you do:
ans = []
for x in my_list:
ans.append(9 * x)

Python produce alternative numbers list from a list of n numbers

I have a list of n numbers. I want to group them in g groups. Also, I want to reverse elements in every odd group. Finally, I would combine all elements in even and odd groups into a new sublist. First I am giving what answer I am expecting and where I went wrong:
Expected answer:
num = 14
grp = 4
# A list of num natural numbers arranged in group (row) of 4 numbers
lst =
[0,1,2,3,
4,5,6,7,
8,9,10,11,
12,13]
lst =
[[0,1,2,3],
[4,5,6,7],
[8,9,10,11],
[12,13]]
# Reverse elements in odd rows
newlst =
[[0,1,2,3],
[7,6,5,4], # reversed here
[8,9,10,11],
[13,12]] # reversed here
# combine elements in all sublists by their position
# combine first element in all sublists into a new sublist
sollst =
[[0,7,8,13],[1,6,9,12],[2,5,10],[3,4,11]]
My solution:
num = 14
grp = 4
#### print
lst= list(range(0,num,1))
newlst= [lst[i:i+grp:1] for i in range(0,num,grp)]
evnlst = newlst[0::2]
oddlst = newlst[1::2]
newoddlst = [oddlst [i][::-1] for i in range(len(oddlst))]
sollst= evnlst + newoddlst
# This gives [[0, 1, 2, 3], [8, 9, 10, 11], [7, 6, 5, 4], [13, 12]]
from itertools import zip_longest
print([[x for x in t if x is not None] for t in zip_longest(fevngps)])
Present answer:
I reached the one step before the final answer and now I have to combine the lists of different lengths and I am running into an error
TypeError: 'int' object is not subscriptable
One approach:
from itertools import zip_longest
num = 14
grp = 4
lst = list(range(0, num, 1))
newlst = [lst[i:i + grp:1] for i in range(0, num, grp)]
# build new list where the sub-list are reversed if in odd indices
revlst = [lst[::-1] if i % 2 == 1 else lst for i, lst in enumerate(newlst)]
# zip using zip_longest and filter out the None values (the default fill value of zip_longest)
result = [[v for v in vs if v is not None] for vs in zip_longest(*revlst)]
print(result)
Output
[[0, 7, 8, 13], [1, 6, 9, 12], [2, 5, 10], [3, 4, 11]]

Get sum of elements in a list python

Given :
[1, 3, 46, 1, 3, 9]
Find distinct combination between these to get target number = 47, as many as possible. 46 + 1 and 1 + 46 are consider same.
My code :
def stockPairs(stocksProfit, target):
# Write your code here
print(stocksProfit)
#print(target)
count = 0
for t, sp in enumerate(stocksProfit):
#print(stocksProfit[t])
for l in range(1, len(stocksProfit)):
total = stocksProfit[t] + stocksProfit[l]
#print(total, stocksProfit[t], stocksProfit[l] )
if total == target :
count = count + 1
return count
expected outcome is 1, since I only want distinct combination
Solution 1 : Combination of any 2 numbers
import itertools
input_list=[1, 3, 46, 1, 3, 9]
combinations_of_2 = itertools.combinations(input_list,2)
sum_of_47 = [ sorted(combination) for combination in combinations_of_2 if sum(combination) == 47 ]
print(sum_of_47)
Output
[[1, 46], [1, 46]]
Solution 2 : Combination of any number of elements from the list
import itertools
input_list=[1, 3,44,2, 1, 3, 9]
all_combinations = [ itertools.combinations(input_list, r) for r in range(len(input_list)+1) ]
sum_of_47 = [ sorted(combination) for combination_by_len in all_combinations for combination in combination_by_len if sum(combination) == 47 ]
print(sum_of_47)
Output
[[3, 44], [3, 44], [1, 2, 44], [1, 2, 44]]
Note: Both solutions will have duplicates.Need to pass through a logic to remove duplicate tuples

Various list concatenation method and their performance

I was working on an algorithm and in that, we are trying to write every line in the code such that it adds up a good performance to the final code.
In one situation we have to add lists (more than two specifically). I know some of the ways to join more than two lists also I have looked upon StackOverflow but none of the answers are giving account on the performance of the method.
Can anyone show, what are the ways we can join more than two lists and their respective performance?
Edit : The size of the list is varying from 2 to 13 (to be specific).
Edit Duplicate : I have been specifically asking for the ways we can add and their respected questions and in duplicate question its limited to only 4 methods
There are multiples ways using which you can join more than two list.
Assuming that we have three list,
a = ['1']
b = ['2']
c = ['3']
Then, for joining two or more lists in python,
1)
You can simply concatenate them,
output = a + b + c
2)
You can do it using list comprehension as well,
res_list = [y for x in [a,b,c] for y in x]
3)
You can do it using extend() as well,
a.extend(b)
a.extend(c)
print(a)
4)
You can do it by using * operator as well,
res = [*a,*b,*c]
For calculating performance, I have used timeit module present in python.
The performance of the following methods are;
4th method < 1st method < 3rd method < 2nd [method on the basis of
time]
That means If you are going to use " * operator " for concatenation of more than two lists then you will get the best performance.
Hope you got what you were looking for.
Edit:: Image showing performance of all the methods (Calculated using timeit)
I did some simple measurements, here are my results:
import timeit
from itertools import chain
a = [*range(1, 10)]
b = [*range(1, 10)]
c = [*range(1, 10)]
tests = ("""output = list(chain(a, b, c))""",
"""output = a + b + c""",
"""output = [*chain(a, b, c)]""",
"""output = a.copy();output.extend(b);output.extend(c);""",
"""output = [*a, *b, *c]""",
"""output = a.copy();output+=b;output+=c;""",
"""output = a.copy();output+=[*b, *c]""",
"""output = a.copy();output += b + c""")
results = sorted((timeit.timeit(stmt=test, number=1, globals=globals()), test) for test in tests)
for i, (t, stmt) in enumerate(results, 1):
print(f'{i}.\t{t}\t{stmt}')
Prints on my machine (AMD 2400G, Python 3.6.7):
1. 6.010000106471125e-07 output = [*a, *b, *c]
2. 7.109999842214165e-07 output = a.copy();output += b + c
3. 7.720000212430023e-07 output = a.copy();output+=b;output+=c;
4. 7.820001428626711e-07 output = a + b + c
5. 1.0520000159885967e-06 output = a.copy();output+=[*b, *c]
6. 1.4030001693754457e-06 output = a.copy();output.extend(b);output.extend(c);
7. 1.4820000160398195e-06 output = [*chain(a, b, c)]
8. 2.525000127207022e-06 output = list(chain(a, b, c))
If you are going to concatenate a variable number of lists together, your input is going to be a list of lists (or some equivalent collection). The performance tests need to take this into account because you are not going to be able to do things like list1+list2+list3.
Here are some test results (1000 repetitions):
option1 += loop 0.00097 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
option2 itertools.chain 0.00138 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
option3 functools.reduce 0.00174 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
option4 comprehension 0.00188 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
option5 extend loop 0.00127 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
option6 deque 0.00180 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
This would indicate that a += loop through the list of lists is the fastest approach
And the source to produce them:
allLists = [ list(range(10)) for _ in range(5) ]
def option1():
result = allLists[0].copy()
for lst in allLists[1:]:
result += lst
return result
from itertools import chain
def option2(): return list(chain(*allLists))
from functools import reduce
def option3():
return list(reduce(lambda a,b:a+b,allLists))
def option4(): return [ e for l in allLists for e in l ]
def option5():
result = allLists[0].copy()
for lst in allLists[1:]:
result.extend(lst)
return result
from collections import deque
def option6():
result = deque()
for lst in allLists:
result.extend(lst)
return list(result)
from timeit import timeit
count = 1000
t = timeit(lambda:option1(), number = count)
print(f"option1 += loop {t:.5f}",option1()[:15])
t = timeit(lambda:option2(), number = count)
print(f"option2 itertools.chain {t:.5f}",option2()[:15])
t = timeit(lambda:option3(), number = count)
print(f"option3 functools.reduce {t:.5f}",option3()[:15])
t = timeit(lambda:option4(), number = count)
print(f"option4 comprehension {t:.5f}",option4()[:15])
t = timeit(lambda:option5(), number = count)
print(f"option5 extend loop {t:.5f}",option5()[:15])
t = timeit(lambda:option6(), number = count)
print(f"option6 deque {t:.5f}",option6()[:15])

moving elements in a list of Python

I have a list of integers; it contains the integer 27, but we don't know its index.
We have to find the index and then swap it with the item following it. If the index of 27 is the last element (list[-1]) than we swap 27 with the first element.
my_list = [1, 2, 3, 4, 27] # original
my_list = [27, 2, 3, 4, 1] # result
I know how to swap 27 when it is not the last element, but I don't know how to swap 27 with the first element like in the example I showed.
Once the number you are looking for always exists in the list just index and swap using modulo:
my_list = [1, 2, 3, 4, 27]
def swap(l,n):
ln = len(l)
ind = my_list.index(n)
l[ind], l[(ind + 1)% ln] = l[(ind + 1) % ln], l[ind]
Using % ln just mean we wrap around so when ind = 5 as per your example (4 + 1) % 5 will be 0
Output:
In [45]: my_list = [1, 2, 3, 4, 27]
In [46]: swap(my_list, 27)
In [47]: my_list
Out[47]: [27, 2, 3, 4, 1]
In [48]: swap(my_list, 4)
In [49]: my_list
Out[49]: [27, 2, 3, 1, 4]
You might want to handle the case where n does not exist:
def swap(l,n):
ln = len(l)
try:
ind = my_list.index(n)
l[ind], l[(ind + 1)% ln] = l[(ind + 1) % ln], l[ind]
except IndexError:
pass
What you do in the except is up to you.

Categories