List recursion? - python

I wrote a function:
def expandList(aList):
"""expand a list"""
finalList = []
for j in aList:
tempList = []
if type(j) != type(list):
tempList.append(j)
finalList.extend(tempList)
else:
finalList.extend(expandList(j))
return finalList
to expand nested list within themselves like:
[[1, [2, 3], [3, 2]], [2, [1, 3], [3, 1]], [3, [1, 2], [2, 1]]]
into:
[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
or
[[1, [2, [3, 4], [4, 3]], [3, [2, 4], [4, 2]], [4, [2, 3], [3, 2]]],
[2, [1, [3, 4], [4, 3]], [3, [1, 4], [4, 1]], [4, [1, 3], [3, 1]]],
[3, [1, [2, 4], [4, 2]], [2, [1, 4], [4, 1]], [4, [1, 2], [2, 1]]],
[4, [1, [2, 3], [3, 2]], [2, [1, 3], [3, 1]], [3, [1, 2], [2, 1]]]]
into:
[[1, 2, 3, 4],[1, 2, 4, 3],[1, 3, 2, 4],
[1, 3, 4, 2],[1, 4, 3, 2],[1, 4, 2, 3],[2, 1, 3, 4],
[2, 1, 4, 3],[2, 3, 1, 4],[2, 3, 4, 1],[2, 4, 1, 3],
[2, 4, 3, 1],[3, 1, 2, 4],[3, 1, 4, 2],[3, 2, 1, 4],
[3, 2, 4, 1],[3, 4, 1, 2],[3, 4, 2, 1],[4, 1, 2, 3],
[4, 1, 3, 2],[4, 2, 1, 3],[4, 2, 3, 1],[4, 3, 1, 2],
[4, 3, 2, 1]]
and so forth. I wish to be able to do this in any size of nested lists.
My function doesn't seem to work right. What am I doing wrong? How can I fix/improve my function?
Thank you in advance

First of all using following command is a wrong way for checking the list type :
type(j) != type(list)
because type(list) returns <type 'type'> actually you are getting the type of a type object that is a type.
In edition you don't need to loop over your sub list and using extend method although you used it incorrect.Since your numbers are in the first index you can just convert it to list and append the rest to it.
You can use a simple list comprehension :
>>> [[[i[0]]+j for j in i[1:]] for i in l]
[[[1, 2, 3], [1, 3, 2]], [[2, 1, 3], [2, 3, 1]], [[3, 1, 2], [3, 2, 1]]]

Related

Count set of elements in numpy array

i have numpy array
array([[1, 2, 3],
[1, 2, 5],
[3, 4, 6],
[2, 5, 4],
[5, 4, 3],
[3, 5, 1],
[2, 5, 1]])
i want function to count how many times set of values appears in array. For example
count_set([1,2])
#output
3
# because set[1,2] appears in elements 0,1,6
I have tried some np.notezero , but it doesnt workout
Use broadcasted comparison with all/any:
a = np.array([[1, 2, 3],
[1, 2, 5],
[3, 4, 6],
[2, 5, 4],
[5, 4, 3],
[3, 5, 1],
[2, 5, 1]])
def count_set(a, elems):
return (a[..., None]==elems).any(-2).all(-1).sum()
count_set(a, [1, 2])
# 3

How can I create a table with 64 combinations with python?

I want to create a table that one column is choosing 3 out of a list [1,2,3,4] randomly with replacement. Then another column is only changing the middle number.
For example,
column 1 column2
111 121
111 131
111 141
121 111
121 131
...
444 414
444 424
444 434
The total should be 64 combinations. I tried combinations_with_replacement()
lst = [1,2,3,4]
ref = list(it.combinations_with_replacement(lst, 3))
>>> print(ref)
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), (3, 3, 3), (3, 3, 4), (3, 4, 4), (4, 4, 4)]
>>> len(ref)
20
but it did not work as I wanted... Any suggestions on how to change?
Thanks
Just as a hint:
col1 = []
col2 = []
for i in range(4):
for j in range(4):
for k in range(4):
col1.append([i + 1, j + 1, k + 1])
for l in range(3):
col2.append([i + 1, (j + l + 1) % 4 + 1, k + 1])
print ("The list\n" + str(col1) + "\nhas " + str(len(col1)) + " entries")
print ("The list\n" + str(col2) + "\nhas " + str(len(col2)) + " entries")
This yields:
The list
[[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 2, 1], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 3, 1], [1, 3, 2], [1, 3, 3], [1, 3, 4], [1, 4, 1], [1, 4, 2], [1, 4, 3], [1, 4, 4], [2, 1, 1], [2, 1, 2], [2, 1, 3], [2, 1, 4], [2, 2, 1], [2, 2, 2], [2, 2, 3], [2, 2, 4], [2, 3, 1], [2, 3, 2], [2, 3, 3], [2, 3, 4], [2, 4, 1], [2, 4, 2], [2, 4, 3], [2, 4, 4], [3, 1, 1], [3, 1, 2], [3, 1, 3], [3, 1, 4], [3, 2, 1], [3, 2, 2], [3, 2, 3], [3, 2, 4], [3, 3, 1], [3, 3, 2], [3, 3, 3], [3, 3, 4], [3, 4, 1], [3, 4, 2], [3, 4, 3], [3, 4, 4], [4, 1, 1], [4, 1, 2], [4, 1, 3], [4, 1, 4], [4, 2, 1], [4, 2, 2], [4, 2, 3], [4, 2, 4], [4, 3, 1], [4, 3, 2], [4, 3, 3], [4, 3, 4], [4, 4, 1], [4, 4, 2], [4, 4, 3], [4, 4, 4]]
has 64 entries
The list
[[1, 2, 1], [1, 3, 1], [1, 4, 1], [1, 2, 2], [1, 3, 2], [1, 4, 2], [1, 2, 3], [1, 3, 3], [1, 4, 3], [1, 2, 4], [1, 3, 4], [1, 4, 4], [1, 3, 1], [1, 4, 1], [1, 1, 1], [1, 3, 2], [1, 4, 2], [1, 1, 2], [1, 3, 3], [1, 4, 3], [1, 1, 3], [1, 3, 4], [1, 4, 4], [1, 1, 4], [1, 4, 1], [1, 1, 1], [1, 2, 1], [1, 4, 2], [1, 1, 2], [1, 2, 2], [1, 4, 3], [1, 1, 3], [1, 2, 3], [1, 4, 4], [1, 1, 4], [1, 2, 4], [1, 1, 1], [1, 2, 1], [1, 3, 1], [1, 1, 2], [1, 2, 2], [1, 3, 2], [1, 1, 3], [1, 2, 3], [1, 3, 3], [1, 1, 4], [1, 2, 4], [1, 3, 4], [2, 2, 1], [2, 3, 1], [2, 4, 1], [2, 2, 2], [2, 3, 2], [2, 4, 2], [2, 2, 3], [2, 3, 3], [2, 4, 3], [2, 2, 4], [2, 3, 4], [2, 4, 4], [2, 3, 1], [2, 4, 1], [2, 1, 1], [2, 3, 2], [2, 4, 2], [2, 1, 2], [2, 3, 3], [2, 4, 3], [2, 1, 3], [2, 3, 4], [2, 4, 4], [2, 1, 4], [2, 4, 1], [2, 1, 1], [2, 2, 1], [2, 4, 2], [2, 1, 2], [2, 2, 2], [2, 4, 3], [2, 1, 3], [2, 2, 3], [2, 4, 4], [2, 1, 4], [2, 2, 4], [2, 1, 1], [2, 2, 1], [2, 3, 1], [2, 1, 2], [2, 2, 2], [2, 3, 2], [2, 1, 3], [2, 2, 3], [2, 3, 3], [2, 1, 4], [2, 2, 4], [2, 3, 4], [3, 2, 1], [3, 3, 1], [3, 4, 1], [3, 2, 2], [3, 3, 2], [3, 4, 2], [3, 2, 3], [3, 3, 3], [3, 4, 3], [3, 2, 4], [3, 3, 4], [3, 4, 4], [3, 3, 1], [3, 4, 1], [3, 1, 1], [3, 3, 2], [3, 4, 2], [3, 1, 2], [3, 3, 3], [3, 4, 3], [3, 1, 3], [3, 3, 4], [3, 4, 4], [3, 1, 4], [3, 4, 1], [3, 1, 1], [3, 2, 1], [3, 4, 2], [3, 1, 2], [3, 2, 2], [3, 4, 3], [3, 1, 3], [3, 2, 3], [3, 4, 4], [3, 1, 4], [3, 2, 4], [3, 1, 1], [3, 2, 1], [3, 3, 1], [3, 1, 2], [3, 2, 2], [3, 3, 2], [3, 1, 3], [3, 2, 3], [3, 3, 3], [3, 1, 4], [3, 2, 4], [3, 3, 4], [4, 2, 1], [4, 3, 1], [4, 4, 1], [4, 2, 2], [4, 3, 2], [4, 4, 2], [4, 2, 3], [4, 3, 3], [4, 4, 3], [4, 2, 4], [4, 3, 4], [4, 4, 4], [4, 3, 1], [4, 4, 1], [4, 1, 1], [4, 3, 2], [4, 4, 2], [4, 1, 2], [4, 3, 3], [4, 4, 3], [4, 1, 3], [4, 3, 4], [4, 4, 4], [4, 1, 4], [4, 4, 1], [4, 1, 1], [4, 2, 1], [4, 4, 2], [4, 1, 2], [4, 2, 2], [4, 4, 3], [4, 1, 3], [4, 2, 3], [4, 4, 4], [4, 1, 4], [4, 2, 4], [4, 1, 1], [4, 2, 1], [4, 3, 1], [4, 1, 2], [4, 2, 2], [4, 3, 2], [4, 1, 3], [4, 2, 3], [4, 3, 3], [4, 1, 4], [4, 2, 4], [4, 3, 4]]
has 192 entries
itertools.combinations_with_replacement will sort the results and remove duplicates. (1,2,1) will be sorted to (1,1,2) and removed because (1,1,2) already exists. What you are looking for is itertools.product.
lst = [1,2,3,4]
ref = list(it.product(lst, repeat=3))
>>> len(ref)
64

List with non-repeating sublists from given list

How to create a list with n-size non-repeating sublists from given list?
I think the example will explain a lot.
given_list = [1, 2, 3, 4, 5]
n = 3
desired_list = [[1,2,3], [1,2,4], [1,2,5], [1,3,4], [1,3,5], [1,4,5], [2,3,4], [2,3,5], [2,4,5], [3,4,5]]
EDIT:
I forgot to add some important combinations
Not sure if you want combinations or permutations, so here are both:
Permutations
You can use permutations from itertools to find all permutations of a given list:
from itertools import permutations
given_list = [1, 2, 3, 4, 5]
n = 3
print([list(i) for i in permutations(given_list, n)])
Output:
[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 2], [1, 3, 4], [1, 3, 5], [1, 4, 2], [1
, 4, 3], [1, 4, 5], [1, 5, 2], [1, 5, 3], [1, 5, 4], [2, 1, 3], [2, 1, 4], [2, 1
, 5], [2, 3, 1], [2, 3, 4], [2, 3, 5], [2, 4, 1], [2, 4, 3], [2, 4, 5], [2, 5, 1
], [2, 5, 3], [2, 5, 4], [3, 1, 2], [3, 1, 4], [3, 1, 5], [3, 2, 1], [3, 2, 4],
[3, 2, 5], [3, 4, 1], [3, 4, 2], [3, 4, 5], [3, 5, 1], [3, 5, 2], [3, 5, 4], [4,
1, 2], [4, 1, 3], [4, 1, 5], [4, 2, 1], [4, 2, 3], [4, 2, 5], [4, 3, 1], [4, 3,
2], [4, 3, 5], [4, 5, 1], [4, 5, 2], [4, 5, 3], [5, 1, 2], [5, 1, 3], [5, 1, 4]
, [5, 2, 1], [5, 2, 3], [5, 2, 4], [5, 3, 1], [5, 3, 2], [5, 3, 4], [5, 4, 1], [
5, 4, 2], [5, 4, 3]]
Combinations
And you can use combinations from itertools to find all the combinations of a given list:
from itertools import combinations
given_list = [1, 2, 3, 4, 5]
n = 3
print([list(i) for i in combinations(given_list, n)])
Output:
[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2
, 3, 5], [2, 4, 5], [3, 4, 5]]
A fast implementation of permutations:
sub perm {
my ($init,$k) = #_;
my $n=length($init); my $dn=$n;
my $out=""; my $m=$k;
for (my $i=0;$i<$n;$i++) {
my $ind=$m % $dn;
$out.=substr($init,$ind,1);
$m=$m / $dn;
$dn--;
substr($init,$ind,1,substr($init,$dn,1));
}
return $out
}
k = 0 .. length(init)-1; each k giving an unique permutation, seemly randomly.
to calculate the factorial length(init)!
sub fac {
my ($f) = #_;
my $fac=1; while ($f>1) { $fac*=$f; $f-- } return $fac
}

Two Slices for Nested List

There is one nested list [[1, 1], [2, 2], [3, 3], [4,4]].
I would like to iterate the list by three slices. I belong to [0, 3], j=i-1, k=i-2
For example:
slice 1: [3, 3], [4, 4]
slice 2: [2, 2], [3, 3]
slice 3: [1, 1], [2, 2]
How can I do it?
You can try this:
s = [[1, 1], [2, 2], [3, 3], [4,4]]
new_s = {"slice {}".format(len(s)-i-1):[s[i], s[i+1]] for i in range(len(s)-1)}
Output:
{'slice 1': [[3, 3], [4, 4]], 'slice 3': [[1, 1], [2, 2]], 'slice 2': [[2, 2], [3, 3]]}
Using zip() you can create that output like:
Code:
new_data = list(zip(reversed(data[:-1]), reversed(data)))
Test Code:
data = [[1, 1], [2, 2], [3, 3], [4, 4]]
new_data = list(zip(reversed(data[:-1]), reversed(data)))
print(new_data)
And if you want a dict from that:
new_data = {'slice_{}'.format(i): d for i, d in
enumerate(zip(reversed(data[:-1]), reversed(data)), 1)}
print(new_data)
Results:
[([3, 3], [4, 4]), ([2, 2], [3, 3]), ([1, 1], [2, 2])]
{'slice_1': ([3, 3], [4, 4]), 'slice_2': ([2, 2], [3, 3]), 'slice_3': ([1, 1], [2, 2])}

[Python]: generate and array of all possible combinations

I have a very straightforward combination problem. I have two arrays (a and b). Array a indicates all the values one of the three slots in array b can take on. Each slot in array b can have a value between 1 and 5. An example of which would be [1, 4, 5]. I would like to generate an array (c) with all possible combinations. I like to extend the basic example larger arrays.
Input:
a = [1, 2, 3, 4, 5]
b = [1, 2, 3]
Output:
c = [[1, 1, 1], [1, 1, 2],[1, 1, 3], [1, 1, 4], [1, 1, 5],
[1, 2, 1], [1, 2, 2],[1, 2, 3], [1, 2, 4], [1, 2, 5],
[1, 3, 1], [1, 3, 2],[1, 3, 3], [1, 3, 4], [1, 3, 5],
[1, 4, 1], [1, 4, 2],[1, 4, 3], [1, 4, 4], [1, 4, 5],
[1, 5, 1], [1, 5, 2],[1, 5, 3], [1, 5, 4], [1, 5, 5],
[2, 1, 1], [2, 1, 2],[2, 1, 3], [2, 1, 4], [2, 1, 5],
[2, 2, 1], [2, 2, 2],[2, 2, 3], [2, 2, 4], [2, 2, 5],
[2, 3, 1], [2, 3, 2],[2, 3, 3], [2, 3, 4], [2, 3, 5],
[2, 4, 1], [2, 4, 2],[2, 4, 3], [2, 4, 4], [2, 4, 5],
[2, 5, 1], [2, 5, 2],[2, 5, 3], [2, 5, 4], [2, 5, 5],
[3, 1, 1], [3, 1, 2],[3, 1, 3], [3, 1, 4], [3, 1, 5],
[3, 2, 1], [3, 2, 2],[3, 2, 3], [3, 2, 4], [3, 2, 5],
[3, 3, 1], [3, 3, 2],[3, 3, 3], [3, 3, 4], [3, 3, 5],
[3, 4, 1], [3, 4, 2],[3, 4, 3], [3, 4, 4], [3, 4, 5],
[3, 5, 1], [3, 5, 2],[3, 5, 3], [3, 5, 4], [3, 5, 5],
[4, 1, 1], [4, 1, 2],[4, 1, 3], [4, 1, 4], [4, 1, 5],
[4, 2, 1], [4, 2, 2],[4, 2, 3], [4, 2, 4], [4, 2, 5],
[4, 3, 1], [4, 3, 2],[4, 3, 3], [4, 3, 4], [4, 3, 5],
[4, 4, 1], [4, 4, 2],[4, 4, 3], [4, 4, 4], [4, 4, 5],
[5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5],
[5, 1, 1], [5, 1, 2],[5, 1, 3], [5, 1, 4], [5, 1, 5],
[5, 2, 1], [5, 2, 2],[5, 2, 3], [5, 2, 4], [5, 2, 5],
[5, 3, 1], [5, 3, 2],[5, 3, 3], [5, 3, 4], [5, 3, 5],
[5, 4, 1], [5, 4, 2],[5, 4, 3], [5, 4, 4], [5, 4, 5],
[5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5]]
Solution for the problem above:
d = []
for i in range(len(a)):
for j in range(len(a)):
for k in range(len(a)):
e = []
e.append(i+1)
e.append(j+1)
e.append(k+1)
d.append(e)
I am looking for a more generic way. One which can accommodate larger arrays (see below) without the need to use a nested for loop structure. I searched for a comparable example, but was unable to find one on stackoverflow.
Input:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
You are looking for itertools.product().
a = [1, 2, 3, 4, 5]
b = 3 # Actually, you just need the length of the array, values do not matter
c = itertools.product(a, repeat=b)
Note that this returns an iterator, you may need to cast it using list() but be aware this can take forever and highly consume memory if the sizes grow.
In the general case, you should of course use the itertools module, in this particular case itertools.product, as explained in the other answer.
If you want to implement the function yourself, you can use recursion to make it applicable to any array sizes. Also, you should probably make it a generator function (using yield instead of return), as the result could be rather long. You can try something like this:
def combinations(lst, num):
if num > 0:
for x in lst:
for comb in combinations(lst, num - 1):
yield [x] + comb
else:
yield []

Categories