Python 3 list of all possible cohesive combinations - python

Hi I'm trying to make a list of all possible cohesive combinations of another list, so from [0, 1, 2, 3] I'd like to get [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]. So far I've got this:
def expandArray(arr):
result = []
for x in range(0, len(arr)):
subArray = [arr[x]]
result.append(subArray)
for y in range(x + 1, len(arr)):
subArray.append(arr[y])
result.append(subArray)
return(result)
But this returns: [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [2, 3], [2, 3], [3]].
What am I doing wrong ?

subArray is a list that you modify in your for loop. When you append to it, you do not create a new list, but you modify it, and then put it in the list again, so will in the end get a result with several copies of the same list. Compare this code:
a = []
b = [5]
a.append(b)
b.append(1)
a.append(b)
print(a)
would output:
[[5, 1], [5, 1]]

Here is a way to have your desired output using list slicing:
def get_combs(iterable):
for k, _ in enumerate(iterable):
elm = k
while elm <= len(iterable):
data = iterable[k:elm]
elm += 1
if data:
yield data
combs = list(get_combs([0, 1, 2, 3]))
print(combs)
Output:
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

Related

Get list for duplicates on an other list python

I need help to get a list from an other :
input :
[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
output wanted :
[0, 0, 1, 0, 0, 1, 2, 3]
I tried to use enumerate but I fail, any suggestion ?
Edit : Every time I meet a new element in the list, I associate this new element with a number (start from 0 and +1 every new element) and if I recognize it later I put the same number, so [1,1] --> 0 because is the first element we met and [2,2] --> 1 etc...
Okay I found a solution :
One more thing before, my example is bad because I can have [1,2] in element of the list for input
the solution I found is
line = [[1, 1], [1, 1], [2, 2], [1, 1], [2, 1], [2, 2], [3, 3], [4, 4]]
p = []
line_not = []
k = 0
for i in range (len(line)):
if line[i] in line[:i]:
p.append(line_not[:k].index(line[i]))
else:
p.append(k)
line_not.append(line[i])
k+=1
the output is :
[0, 0, 1, 0, 2, 1, 3, 4]
If u have a better solution, tell me !
try to make a map, this works:
inp=[[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = [0, 0, 1, 0, 0, 1, 2, 3]
mymap={inp[0][0]:0}
output = [0]
k_count=1
for i in inp[1:]:
if i[0] in mymap.keys():
output.append(mymap[i[0]])
else:
mymap[i[0]] = k_count
output.append(mymap[i[0]])
k_count+=1
and then output == [0, 0, 1, 0, 0, 1, 2, 3]
First build a dictionary that does the assocation of each unique element with a number:
>>> x = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
>>> d = {}
>>> for [i, _] in x:
... if i not in d:
... d[i] = len(d)
...
and then you can easily build your output list by doing lookups in that dictionary:
>>> [d[i] for [i, _] in x]
[0, 0, 1, 0, 0, 1, 2, 3]
this would work in your current example, but it is not a comprehensive solution. Without context its hard to understand what you are trying to achieve, so use with care:
import numpy as np
inp = [[1, 1], [1, 1], [2, 2], [1, 1], [1, 1], [2, 2], [3, 3], [4, 4]]
out = np.array([i[0] for i in inp]) - 1
print(out) # result: [0 0 1 0 0 1 2 3]

how to merge lists in list (without numpy)

This is what i have-
def merge_list(mylist)
list1 = []
one_len = len(mylist)
two_len = len(mylist[0][0])
for index in range(two_len):
combine_list = []
for index2 in range(one_len):
combine_list.extend([a[index] for a in mylist[
index2]])
list1.append(combine_list)
return list1
But i have a problem with the output-
for example:
input-
mylist=[[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]], [[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]]]
in short-
[[[1]*3]*4, [[2]*3]*4, [[3]*3]*4]
the output is -
[[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]]
and not -
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]
in short-
[[[1, 2, 3]]*3]*4
I would be happy to solve the problem and advise how to shorten the code.
In order to fix your code, you just need to update the return statement like this:
return [list1]
Though there is still a hidden problem when your inner lists lengths are longer than one element. Check your outputs with sample inputs like [[[2,1], [3,1]]].
One further - more compact - solution may be obtained by concatenating the inner lists within a cycle, then recreate the number of dimensions you need, moving the complexity from O(n^2) to O(n).
mylist = [[[2,1]],[[3,1]]]
def merge_list(mylist):
l_out = []
for l in mylist:
l_out += l[0]
return [[l_out]]
EDIT: In case of more complex inputs, you can extract first all elements and eventually fix the dimensions. This will still bring O(n^2) complexity though:
def merge_list(lst):
elements = [[] for _ in range(len(mylist[0]))]
for l1 in mylist:
for idx, l2 in enumerate(l1):
elements[idx] += l2
return [elements]
merge_list(mylist)
Input:
[[[1], [1]], [[2], [2]], [[3], [3]]]
Output:
[[[1, 2, 3], [1, 2, 3]]]

How to reorder a list composed of lists

I am trying to tranform
[[1, 2, 3], [1, 2]]
into
[[1, 2, 3], [3, 2, 1], [2, 3, 1], [1, 2], [2, 1]]
But instead of the correct output, I am getting this:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2], [1, 2]]
Here is my code
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append(listTemp)
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
In your for loop, you are adding the same list again and again, but instead, you should make a copy of the list in the iteration.
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append([x for x in listTemp])
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
Output:
[[1, 2, 3], [3, 1, 2], [2, 3, 1], [1, 2], [2, 1]]

How to make this code more optimized in terms of time?

I have a written the code here but it is taking much time. I need to optimize it more. The k here varies, it can be 2 or 3 or 4, depends on the user. Please help me out here.
from itertools import combinations
def get_all_combinations(input_list, k):
for item in combinations(input_list, k):
yield list(set(list(item)))
input_list = [1, 2, 1, 2, 3]
k = 3
lst = []
for i in range(1, k + 1):
for item in get_all_combinations(input_list, i):
if len(item) > i - 1:
lst.append(item)
print(len(lst))
>>17
#[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
Try this one:
>>> input_list = [1, 2, 1, 2, 3]
>>> k = 3
>>> [list(set(el)) for i in range(1, k+1) for el in itertools.combinations(input_list, i) if len(set(el))>i-1]
[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
With the following version your processing will go nearly twice as fast:
from itertools import combinations
def get_all_combinations(input_list, k):
for i in range(1, k + 1):
for item in combinations(input_list, i):
s = set(item)
if len(s) >= i:
yield list(s)
input_list = [1, 2, 1, 2, 3]
k = 3
lst = list(get_all_combinations(input_list, k))
print(lst)
The output remains the same:
[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
Test this:
from itertools import combinations
def get_all_combinations(input_list,k):
l = []
for item in combinations(input_list, k):
l.append( list(set(list(item))))
return l
input_list = [1, 2, 1, 2, 3]
k = 3
lst = []
for i in range(1,k+1):
gac = []
gac = get_all_combinations(input_list, i)
for item in gac:
if len(item) > i-1:
lst.append(item)
print(len(lst))
base on link
If this is meant to be homework, your instructor is probably looking for this.
lst = [list(c) for i in range(k) for c in combinations(input_list, i+1) if len(set(c)) > i]

How to remove a list of indices from list

I have two lists of lists of the same length in Python 3 as follows:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
Elements of A are indices of elements of W. I would like to remove the elements of W given A. So, in the example, I would like to remove W[0][0], W[1][0], W[1][1], W[2][0], W[2][1], W[2][2], etc.
What I did is this:
for t in range(len(A)):
del W[t][A[t]]
But this gives the following error: TypeError: list indices must be integers or slices, not list
Unlike numpy arrays, you cannot index a list with a list. But you can use a list comprehension for this task:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
res = [[j for i, j in enumerate(w) if i not in a] for a, w in zip(A, W)]
print(res)
[[2], [3], [3], [4, 4], []]
Or, if you are happy using a 3rd party library, numpy syntax is simpler:
import numpy as np
res = [np.delete(i, j).tolist() for i, j in zip(W, A)]
One easy way is to use two nested loops. As you have probably noticed by now, you need two index numbers - one for the list in A and another for the element number of this list. Here is one way to tackle the problem:
A = [[0], [0, 1], [0, 1, 2], [0, 1], [0, 1, 2, 3]]
W = [[2, 2], [1, 2, 3], [2, 2, 2, 3], [1, 3, 4, 4], [1, 1, 3, 4]]
#cycle through list A and keep track of the list number i
for i, a_list in enumerate(A):
#retrieve index from each list in A, start with the highest index to avoid index problems
for j in sorted(a_list, reverse = True):
#delete the element j in list i of W
del W[i][j]
print(W)
#output
#[[2], [3], [3], [4, 4], []]

Categories

Resources