how to convert the following code into list comprehensions - python-3.x

I have written the code using for loop, i want the code into list comprehension.
mainLst = [[2],[3],[4],[5],[6],[7],[8]]
lst2 = [[],[],[],[]]
const = 0
for i in range(4):
k = const
for j in range(4):
lst2[const].append(mainLst[k][0])
k += 1
const += 1
print(lst2)
Expecting the above code into list comprehension.

If you want to transform just a loop part and still use mainLst variable, then it will look like:
mainLst = [[2],[3],[4],[5],[6],[7],[8]]
lst2 = [[mainLst[j + k][0] for k in range(4)] for j in range(4)]
print(lst2)
# or if you still want to have initialized lst2 array, then:
lst2 = [[],[],[],[]]
[lst2[j].extend([mainLst[j + k][0] for k in range(4)]) for j in range(4)]
print(lst2)
Both output the same:
[[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

Can be done without creating other variables like k and const
lst2 = [[i for i in range(j, j + 4)] for j in range(2, 6)]

You can use the operator itemgetter with slice to get slices of sublists from the list and chain.from_iterable to merge sublists into one list:
from operator import itemgetter
from itertools import chain
mainLst = [[2],[3],[4],[5],[6],[7],[8]]
[list(chain.from_iterable(itemgetter(slice(i, i + 4))(mainLst))) for i in range(4)]
# [[2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8]]

Related

All possible combinations (including all subsets combinations) of two or more lists

I searched the net but couldn't find anything. I am trying to get all possible combinations including all subsets combinations of two lists (ideally n lists). All combinations should include at least one item from each list.
list_1 = [1,2,3]
list_2 = [5,6]
output = [
[1,5], [1,6], [2,5], [2,6], [3,5], [3,6],
[1,2,5], [1,2,6], [1,3,5], [1,3,6], [2,3,5], [2,3,6], [1,5,6], [2,5,6], [3,5,6],
[1,2,3,5], [1,2,3,6],
[1,2,3,5,6]
]
All I can get is pair combinations like [1,5], [1,6], .. by using
combs = list(itertools.combinations(itertools.chain(*ls_filter_columns), cnt))
What is the pythonic way of achieving this?
Here is one way:
from itertools import combinations, product
def non_empties(items):
"""returns nonempty subsets of list items"""
subsets = []
n = len(items)
for i in range(1,n+1):
subsets.extend(combinations(items,i))
return subsets
list_1 = [1,2,3]
list_2 = [5,6]
combs = [list(p) + list(q) for p,q in product(non_empties(list_1),non_empties(list_2))]
print(combs)
Output:
[[1, 5], [1, 6], [1, 5, 6], [2, 5], [2, 6], [2, 5, 6], [3, 5], [3, 6], [3, 5, 6], [1, 2, 5], [1, 2, 6], [1, 2, 5, 6], [1, 3, 5], [1, 3, 6], [1, 3, 5, 6], [2, 3, 5], [2, 3, 6], [2, 3, 5, 6], [1, 2, 3, 5], [1, 2, 3, 6], [1, 2, 3, 5, 6]]
Which has more elements then the output you gave, though I suspect that your intended output is in error. Note that my code might not correctly handle the case in which there is a non-empty intersection of the two lists. Then again, it might -- you didn't specify what the intended output should be in such a case.
Here is another way.
Even though it is not fancy, it cares n_lists easily.
def change_format(X):
output = []
for x in X:
output += list(x)
return output
import itertools
list_1 = [1,2,3]
list_2 = [5,6]
list_3 = [7,8]
lists = [list_1, list_2, list_3]
lengths = list(map(len, lists))
rs_list = itertools.product(*[list(range(1, l+1)) for l in lengths])
output = []
for rs in rs_list:
temp = []
for L, r in zip(lists, rs):
temp.append(list(itertools.combinations(L, r)))
output += list(itertools.product(*temp))
output = list(map(change_format, output))
I have managed to make it work for n-lists with less code, which was a challenge for me.
from itertools import chain, combinations, product
def get_subsets(list_of_lists):
"""
Get all possible combinations of subsets of given lists
:param list_of_lists: consists of any number of lists with any number of elements
:return: list
"""
ls = [chain(*map(lambda x: combinations(e, x), range(1, len(e)+1))) for e in list_of_lists if e]
ls_output = [[i for tpl in ele for i in tpl] for ele in product(*ls)]
return ls_output
list_1 = [1, 2, 3]
list_2 = [5, 6]
list_3 = [7, 8]
ls_filter_columns = [list_1, list_2, list_3]
print(get_subsets(ls_filter_columns))

Lists Splitting Equal Split

I wrote a code that takes a certain input (int) and stores it to a list.
The next phase, which I can't manage to construct is to take the list and split it to 4 equal lists.
So far I take the sum of the prime_list and divide it to 4. the sum stored as var to further use.
prime_list = [1,2,3,4,5,6,7,8,9,10,11,12] split to equal 4 lists, divide by range (or other methods):
split_list_01 = [1,2,3]
split_list_02 = [4,5,6]
split_list_03 = [7,8,9]
split_list_04 = [10,11,12]
Try this:
prime_list = [1,2,3,4,5,6,7,8,9,10,11,12]
new_list = [prime_list[i:i+3] for i in range(0, len(prime_list), 3)]
print new_list
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
A dictionary can be used to store each of the lists using different keys which can be accessed later:
prime_list = [1,2,3,4,5,6,7,8,9,10,11,12]
split_list = {}
count = 0
for i in range(0, len(prime_list), 3):
split_list[count] = prime_list[i:i+3]
count += 1
print split_list
Output:
{0: [1, 2, 3], 1: [4, 5, 6], 2: [7, 8, 9], 3: [10, 11, 12]}

How to merge two array and group by key?

How to merge two array and group by key?
Example:
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
Expected outcome:
[[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
If I understand it right, the list of keys map to the list of values. You can use the zip function to iterate through two lists at the same time. Its convenient in this case. Also check up on the beautiful defaultdict functionality - we can use it to fill a list without initialising it explicitely.
from collections import defaultdict
result = defaultdict(list) # a dictionary which by default returns a list
for key, val in zip(keys, my_list):
result[key].append(val)
result
# {1: [3, 4], 2: [5, 6], 3: [4], 5: [6], 7: [8]}
You can then go to a list (but not sure why you would want to) with:
final = []
for key, val in result.items():
final.append([key] + val) # add key back to the list of values
final
# [[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
I think you have to write it by your own using set() to remove duplicates, so I have made a function called merge_group
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
def merge_group(input_list : list, input_key : list):
result = []
i = 0
while i < len(my_list):
result.append([my_list[i], keys[i]])
i += 1
j = 0
while j < len(result):
if j+1 < len(result):
check_sum = result[j] + result[j+1]
check_sum_set = list(set(check_sum))
if len(check_sum) != len(check_sum_set):
result[j] = check_sum_set
j += 1
return result
print(merge_group(my_list, keys))

Remove by index on nested list

I have a nested list:
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
I want to iterate over the list and return a new nested list with each list returned with one value missing. So:
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
I have this:
temp_list = []
y = 0
for i in x:
temp_list += i.remove(y)
y+=1
print(x)
But what's happening is each iteration is removing the indexed item so the list goes out of range.
list = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
for count, i in enumerate(list):
if len(i) > 0:
del i[count]
print(list)
For each sublist it deletes the element with an index equal to the index of the sublist
>>>[[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
Hope this helps!
You have to use pop instead for remove. See this one:
In [46]: x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
In [47]: new_list = [lst for ind, lst in enumerate(x) if lst.pop(ind)]
In [48]: new_list
Out[48]: [[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
for i in range(0,len(x)):
for j in range (0,len(x)):
if(i==j):
del(x[i][j])
print(x)
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
del(x[i][j]) is used to delete by index from list

using for loop with in a for loop

For a given array v=[1,2,3] I am trying to print the sum of the product of each element with s for a range of s
import numpy as np
v=[1,2,3]
for s in range(0,5):
for i in range (0,3):
tot= np.multiply(v[i],s)
b.append(tot)
print (b)
my output is
[0, 0, 0, 1, 2, 3, 2, 4, 6, 3, 6, 9, 4, 8, 12]
I am trying to get the out put as
[[0, 0, 0], [1, 2, 3], [2, 4, 6], [3, 6, 9], [4, 8, 12]]
I am not quite sure how the second for loop is working inside the first for loop. If someone can explain that, it would be wonderful.
You'd create a new list for each iteration of the outer for loop:
v=[1,2,3]
b = []
for s in range(0,5):
result = []
for i in range (0,3):
tot= np.multiply(v[i],s)
result.append(tot)
b.append(result)
print (b)
You could just use * to multiply values, and you can iterate directly over v (no need to use a range)`:
v = [1, 2, 3]
b = []
for s in range(5):
result = []
for i in v:
result.append(i * s)
b.append(result)
You can replace both loops with list comprehensions:
b = [[i * s for i in v] for s in range(5)]
import numpy as np
v=np.array([1,2,3])
b=[]
for s in range(0,5):
b.append(list(v*s))
print (b)
Should do what you want. Don't forget numpy's extremely powerful broadcasting capability.
v=[1,2,3]
b=[]
for s in range(0,5):
b.append([])
for i in range (0,3):
tot= np.multiply(v[i],s)
b[s].append(tot)
print(b)

Resources