I have a nested array of arbitrary length and trying to retrieve data from it in the following order: items in the [0] element of the array form somewhat like a tree and as a result I should return all possible combinations with them.
For example:
some_list = [[1, 2], [3, 4], [5, 6, 7]]
the result should be:
[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7],
[2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]
I tried loops but they do not seem a good decision.
I think it should be recursion, but don't know how to apply it.
this is an example of a recursive function that would calculate the cartesian product of all the input lists
def cp(x):
l = []
# loop over the lists in the list
# if there is only 1 list left in the input then return it
if len(x) > 1:
for i in x[0]: # loop over the first list in the input
for j in cp(x[1:]): # loop over the cartesian product of the remaining lists in the input
l.append([i]) # add a new sub-list starting with value of i
if isinstance(j,list): # extend it with the result of the cartesian product of the remaining lists
l[-1].extend(j)
else:
l[-1].append(j)
else:
l = x[0]
return l
print(cp([[1, 2], [3, 4], [5, 6, 7]]))
gives the output
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]
have a look here for implementations in different programming languages:
https://rosettacode.org/wiki/Cartesian_product_of_two_or_more_lists
You can do it with nested for loops, or for convenience, with itertools.product:
from itertools import product
some_list = [[1, 2], [3, 4], [5, 6, 7]]
prod = [list(i) for i in product(*some_list)]
print(prod)
Output:
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]
Related
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
I have three lists as follows.
A = [1, 2, 3]; B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]; C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I want to create another list containing all the above inner lists starting from A to C.
Desired = [elements of A, elements of B, elements of C] just like this.
Desired = [[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
It seems like you know which list is nested (B and C) and which isn't (A). If that's the case then you could simply do:
result = [A] + B + C
If you don't know but can determine the nestedness by looking at the first item, then you could do:
result = [
item
for numbers in (A, B, C)
for item in (numbers if isinstance(numbers[0], list) else [numbers])
]
If that's also not the case, i.e. there could be mixed lists (lists that contain numbers and lists), then you could use itertools.groupby from the standard library:
from itertools import groupby
result = []
for key, group in groupby(A + B + C, key=lambda item: isinstance(item, list)):
if not key:
group = [[*group]]
result.extend(group)
Results for all versions (with A, B and C like provided):
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3],
[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
The method I use below is to see if the inner_list contents are infact a list of themselves.
If they are, then append the inner list.
If they are not, then append the outer_list.
A = [1, 2, 3];
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]];
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
desired = []
for outer_list in (A,B,C):
list_state = False
for inner_list in outer_list:
if isinstance(inner_list, list):
desired.append(inner_list)
else:
list_state = True
# Add outer_list only if the inner_list was not a list
if list_state:
desired.append(outer_list)
print(desired)
OUTPUT:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I made something to make a list to an nested list if it is not.
A = [1, 2, 3]
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
listt = [ 'A', 'B', 'C' ]
des = []
for i in listt:
if type((globals()[i])[0]) != list:
globals()[i] = [[i for i in globals()[i]]] #turns into nested list if not (line 7-9)
for i in (A,B,C):
for x in i:
des.append(x)
print(des)
Output:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I am looking for an efficient way to transform a given list into another list with degree n
here is input:
lst = [1, 2, 3, 4, 5, 6, 7]
n = 3
And favorable output is this:
[[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
It is basically like every element in resulting list is made of n consecutive elements from the given list except elements at starting and ending n-1 indices: 1, 2, 6, 7 in this example
Also for integer n, 1 <= n <= len(lst) is essential
You can use a comprehension with appropriate slices:
def chunks(lst, n=3):
return [lst[max(i,0):i+n] for i in range(1-n, len(lst))]
chunks([1, 2, 3, 4, 5, 6, 7])
# [[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
chunks([1, 2, 3, 4, 5], 4)
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5]]
chunks([1, 2], 2)
# [[1], [1, 2], [2]]
chunks([1, 2, 3], 1)
# [[1], [2], [3]]
A more elegant version of this sliding window uses a collections.deque (as pointed out by #chepner in the comments):
from collections import deque
def chunks(lst, n=3):
window = deque(maxlen=n)
for x in lst:
window.append(x)
yield list(window)
while len(window) > 1:
window.popleft()
yield list(window)
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
}
I have a list of lists like this: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]. How can I count the lists which are sublists of more than two lists? For example, here [2, 3] and [3, 4] would be the lists that are sublists of first 3 lists. I want to get rid of them.
This comprehension should do it:
data = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
solution = [i for i in data if sum([1 for j in data if set(i).issubset(set(j))]) < 3]
set_list = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
check_list = [[2, 3], [3, 4]]
sublist_to_list = {}
for set in set_list:
for i, sublist in enumerate(check_list):
count = 0
for element in sublist:
if element in set:
count += 1
if count == len(sublist):
if i not in sublist_to_list:
sublist_to_list[i] = [set]
else:
sublist_to_list[i].append(set)
print(sublist_to_list)
Output: {0: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3]], 1: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [3, 4]]}
which means [2, 3] is subset of [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3]]
and [3, 4] is subset of [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [3, 4]]
You can first make a function that gets sub lists of a list:
def sublists(lst):
length = len(lst)
for size in range(1, length + 1):
for start in range(length - size + 1):
yield lst[start:start+size]
Which works as follows:
>>> list(sublists([1, 2, 3, 4, 5]))
[[1], [2], [3], [4], [5], [1, 2], [2, 3], [3, 4], [4, 5], [1, 2, 3], [2, 3, 4], [3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3, 4, 5]]
Then you can use this to collect all the sublists list indices into a collections.defaultdict:
from collections import defaultdict
lsts = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
d = defaultdict(list)
for i, lst in enumerate(lsts):
subs = sublists(lst)
while True:
try:
curr = tuple(next(subs))
d[curr].append(i)
except StopIteration:
break
Which will have tuple keys for the sublists, and the list indices as the values.
Then to determine sub lists that occur more than twice in all the lists, you can check if the set of all the indices has a length of more than two:
print([list(k) for k, v in d.items() if len(set(v)) > 2])
Which will give the following sublists:
[[2], [3], [4], [5], [2, 3], [3, 4], [4, 5], [2, 3, 4], [3, 4, 5], [2, 3, 4, 5]]