sum two lists element-by-element in python recursively [duplicate] - python

This question already has answers here:
Element-wise addition of 2 lists?
(17 answers)
Closed 8 years ago.
Is it possible to recursively sum two lists element by element and then return the new list?
def sumListElements(listOne, listTwo):
list = []
i = 0
while i < len(listOne):
list.append(listOne[i] + listTwo[i])
i += 1
return list
So,
a = [1, 2, 3]
b = [3, 4, 5]
Results
R = [4, 6, 8]

Here is a recursive implementation
def recursive_sum(l1, l2, idx = 0):
if idx < min(len(l1), len(l2)):
return [l1[idx] + l2[idx]] + recursive_sum(l1, l2, idx + 1)
else:
return []
print recursive_sum([1, 2, 3], [4, 5, 6])
# [5, 7, 9]
Or
def recursive_sum(l1, l2, result = None, idx = 0):
if result is None:
result = []
if idx < min(len(l1), len(l2)):
result.append(l1[idx] + l2[idx])
return recursive_sum(l1, l2, result, idx + 1)
else:
return result

Use zip() and map() here:
R = map(sum, zip(a, b))
Demo:
>>> a = [1, 2, 3]
>>> b = [3, 4, 5]
>>> map(sum, zip(a, b))
[4, 6, 8]
For Python 3 compatibility, replace map() with a list comprehension:
[sum(z) for z in zip(a, b)]

Function which takes n lists, and adds each element in an i-th index together with the others:
from itertools import izip_longest
def sum_elements(*lists):
return map(sum, izip_longest(*lists, fillvalue=0))
Showed with your data:
>>> sum_elements([1, 2, 3], [3, 4, 5])
[4, 6, 8]
Lists with uneven lengths still have a nice result:
>>> sum_elements([1, 2, 3], [3, 4, 5, 6])
[4, 6, 8, 6]
And it can take any number of lists:
>>> sum_elements([1, 2, 3], [3, 4, 5, 6], [8,9])
[12, 15, 8, 6]

Related

python get first x elements of a list and remove them

Note: I know there is probably an answer for this on StackOverflow already, I just can't find it.
I need to do this:
>>> lst = [1, 2, 3, 4, 5, 6]
>>> first_two = lst.magic_pop(2)
>>> first_two
[1, 2]
>>> lst
[3, 4, 5, 6]
Now magic_pop doesn't exist, I used it just to show an example of what I need. Is there a method like magic_pop that would help me to do everything in a pythonic way?
Do it in two steps. Use a slice to get the first two elements, then remove that slice from the list.
first_list = lst[:2]
del lst[:2]
If you want a one-liner, you can wrap it in a function.
def splice(lst, start = 0, end = None):
if end is None:
end = len(lst)
partial = lst[start:end]
del lst[start:end]
return partial
first_list = splice(lst, end = 2)
One option would be using slices
def func(lst: list, n: int) -> tuple:
return lst[:n], lst[n:]
lst = [1, 2, 3, 4, 5, 6]
first_two, lst = func(lst, 2)
print(lst)
# [3, 4, 5, 6]
Alternative, here is a kafkaesque approach using builtins:
def func(lst: list, i: int) -> list:
return list(map(lambda _: lst.pop(0), range(i)))
lst = list(range(10))
first_two = func(lst, 2)
print(first_two)
# [0, 1]
print(lst)
# [2, 3, 4, 5, 6, 7, 8, 9]
Try:
lst = [1, 2, 3, 4, 5, 6]
first_two, lst = lst[:2], lst[2:]
print(first_two)
print(lst)
Prints:
[1, 2]
[3, 4, 5, 6]
You can just create a lambda function to do this.
magic_pop = lambda x,y:(x[:y],x[y:]) if y<len(lst) else x
magic_pop(lst,3)
Out[8]: ([1, 2, 3], [4, 5, 6])

Intersection needed for multiple lists without knowing the content of the list

I want to take multiple lists and know the values that appaer in these lists with the possibility of one or more of the lists being empty.
CASE 1:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
c = []
d = [2, 3, 5]
Needed output: 5
CASE 2:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5, 3]
c = [1, 3, 8]
d = []
Needed output: 3
Order doesn't matter.
I know I can use this if there are no empty lists (source 1 / source 2)
list(set(a) & set(b) & set(c) and set(d))
The problem occurs when one of the lists is empty.
Python version: 3.8
Lets use a list comprehension with set.intersection -
The list comprehension checks if the length of the list is greater than 0 and then uses it to find an intersection using set.intersection. The * operator unpacks this list of sets, to individual sets.
Case 1:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
c = []
d = [2, 3, 5]
l = [a,b,c,d]
l = [set(i) for i in l if len(i)>0]
set.intersection(*l)
{5}
Case 2:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5, 3]
c = [1, 3, 8]
d = []
l = [a,b,c,d]
l = [set(i) for i in l if len(i)>0]
set.intersection(*l)
{3}
You use filter() to remove empty lists and then convert your list to set() objects using map() and do the intersection as:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
c = []
d = [2, 3, 5]
my_list = [a, b, c, d]
my_result = set.intersection(*map(set, filter(bool, my_list)))
# where `my_result` holds the value:
# {5}

How to split a nested list of ints into a a list

lst = [[1, 5],
[2, 2]
this is my nested list, I need to make a list of the points of this:
output = [[1, 5, 2, 2]
here is my attempt at this which works for this case but fails if I have an example where the row length is 6 or greater than 4
new_lst = []
for x in range(len(lst)):
for y in range(0, len(lst[x]), 2):
new_lst.append([lst[x][y],lst[x][y+1]])
counter_a = 0
counter_b = 1
output = []
while counter_b - 4 <= len(lst):
output.append(new_lst[counter_a] + new_lst[counter_a + 2])
output.append(new_lst[counter_b] + new_lst[counter_b + 2])
counter_a += 4
counter_b += 4
print(output)
How about this? This is general for all lists with size nxm where n and m are even numbers. The logic is to iterate with a step of 2 in both row and column, then take the block of 2x2 elements and append it to the output list.
lst = [[1, 6, 5, 6],
[2, 5, 6, 8],
[7, 2, 8, 1],
[4, 4, 7, 3]]
output = []
for j in range(0, len(lst), 2):
for i in range(0, len(lst[0]), 2):
output.append([lst[j][i], lst[j][i+1], lst[j+1][i], lst[j+1][i+1]])
output : [[1, 6, 2, 5], [5, 6, 6, 8], [7, 2, 4, 4], [8, 1, 7, 3]]
Try using:
print([x for i in list(zip(*[[i[:2], i[2:]] for i in lst])) for x in [i[0] + i[1], i[2] + i[3]]])

expanding arbitrary number of sublists within a list

I am trying to expand sublists within a list. I wrote it for one layer of sublists within the list. Is there a better way to code this so to scale for arbitrary number of nested lists? See example as follows:
a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]
def expand(x):
# expands a list of lists with no further sublists
a = []
for i in x:
# could also here do a += i and avoid the second for loop
for j in i:
a.append(j)
return a
print expand(c)
Returns the desired [1, 2, 3, 4, 5, 6]
To further clarify, I am wondering how to better scale for
`e = [c, a, b]' and further nested iterations.
c = [[1, 2, 3], [4, 5, 6]]
# first method
res = [x for lst in c for x in lst]
# second method
from itertools import chain
res = list(chain(*c))
Edit: he wants iteratively nested lists!
c = [[[1], [2, 3]], [4, 5], [[6, 7, 8], 9]]
def expand(lst):
try:
for a in lst:
for b in expand(a):
yield b
except TypeError:
yield lst
res = list(expand(c)) # => [1, 2, 3, 4, 5, 6, 7, 8, 9]
Use Recursion:
def flat_list(l):
for a in l:
if isinstance(a, list):
for x in flat_list(a):
yield x
else:
yield a
a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]
e = [c, a, b]
print list(flat_list(c))
print list(flat_list(e))
the output is:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
One solution:
def flatten(ls):
result = []
stack = [ls]
while stack:
if isinstance(stack[-1], list):
try: stack.append(stack[-1].pop(0))
except IndexError: stack.pop() # remove now-empty sublist
else:
result.append(stack.pop())
return result
a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]
e = [c, a, b]
print flatten(e)
Output:
[1, 2, 3, 4, 5, 6]
Or :
Using sum:
>>> e
[[[1, 2, 3], [4, 5, 6]], [1, 2, 3], [4, 5, 6]]
>>> sum(e[0], [])
[1, 2, 3, 4, 5, 6]
Using reduce:
>>> reduce(lambda x,y: x+y, e[0])
[1, 2, 3, 4, 5, 6]
>>>

compare two lists in python and return indices of matched values

For two lists a and b, how can I get the indices of values that appear in both? For example,
a = [1, 2, 3, 4, 5]
b = [9, 7, 6, 5, 1, 0]
return_indices_of_a(a, b)
would return [0,4], with (a[0],a[4]) = (1,5).
The best way to do this would be to make b a set since you are only checking for membership inside it.
>>> a = [1, 2, 3, 4, 5]
>>> b = set([9, 7, 6, 5, 1, 0])
>>> [i for i, item in enumerate(a) if item in b]
[0, 4]
def return_indices_of_a(a, b):
b_set = set(b)
return [i for i, v in enumerate(a) if v in b_set]
For larger lists this may be of help:
for item in a:
index.append(bisect.bisect(b,item))
idx = np.unique(index).tolist()
Be sure to import numpy.
you can do it like this,with no need to set :
a = [1, 2, 3, 4, 5]
b = {9, 7, 6, 5, 1, 0}
[i for i, item in enumerate(a) if item in b]
inspired by #jamylak

Categories