Related
so I will do my best to explain what I'm looking for,
at the moment I have a 100 item list that I want to repetitively shuffle using a set pattern to first check if the pattern will eventually bring me back to where I began
and 2 to print the result of each loop to a text file.
so using a 3 item list as my example
[a,b,c]
and the shuffle pattern [3 1 2]
where the 3rd item becomes the first.
the first item becomes the second
and the second item becomes the 3rd
on a loop would generate the following patterns
[a,b,c]
[3,1,2]
[c,a,b]
[b,c,a]
[a,b,c]
but I have a list at the moment of 100 items that I need to find every single arrangement for a few different patterns I would like to test out.
does anyone know of a way to do this in python please.
You can define function and call this function multi times like below:
>>> def func(lst, ptr):
... return [lst[idx-1] for idx in ptr]
>>> lst = ['a','b','c']
>>> ptr = [3,1,2]
>>> for _ in range(5):
... lst = func(lst, ptr)
... print(lst)
['c', 'a', 'b']
['b', 'c', 'a']
['a', 'b', 'c']
['c', 'a', 'b']
['b', 'c', 'a']
You could use numpy advanced integer indexing if your list contains a numeric type:
import numpy as np
original_list=[1,2,3]
numpy_array = np.array(original_list)
pattern = [2,1,0]
print(numpy_array[pattern])
>>> array([3, 2, 1])
def rearrange(pattern : list,L:list):
new_list = []
for i in pattern :
new_list.append(L[i-1])
return new_list
print(rearrange([3,1,2],['a','b','c']))
output :
['c', 'a', 'b']
Itertools could be what you need.
import itertools
p = itertools.permutations(['a','b','c', 'd'])
list(p)
Output:
[('a', 'b', 'c', 'd'),
('a', 'b', 'd', 'c'),
('a', 'c', 'b', 'd'),
('a', 'c', 'd', 'b'),
('a', 'd', 'b', 'c'),
('a', 'd', 'c', 'b'),
('b', 'a', 'c', 'd'),
('b', 'a', 'd', 'c'),
('b', 'c', 'a', 'd'),
('b', 'c', 'd', 'a'),
('b', 'd', 'a', 'c'),
('b', 'd', 'c', 'a'),
('c', 'a', 'b', 'd'),
('c', 'a', 'd', 'b'),
('c', 'b', 'a', 'd'),
('c', 'b', 'd', 'a'),
('c', 'd', 'a', 'b'),
('c', 'd', 'b', 'a'),
('d', 'a', 'b', 'c'),
('d', 'a', 'c', 'b'),
('d', 'b', 'a', 'c'),
('d', 'b', 'c', 'a'),
('d', 'c', 'a', 'b'),
('d', 'c', 'b', 'a')]
I am trying to get all possible permutations of length 1, 2 and 3 for the charactes "a", "b" and "c"
from itertools import permutations
a = ['a','b', 'c']
perm1 = permutations(a, 1)
perm2 = permutations(a, 2)
perm3 = permutations(a, 3)
p_list = []
p_list.extend(list(perm1))
p_list.extend(list(perm2))
p_list.extend(list(perm3))
str = [[j for j in i] for i in p_list]
print(str[3])
At this point things are expected
When I modify the str = line to this str = [[[''.join(k) for k in j] for j in i] for i in p_list] I would expect to get a list of strings where each permutation is a string with no commas. e.g. ["abc", "a", "b", "c"] etc. but instead I get a list of lists.
First thing: please don't set str as variable.
Below I copied your code, commenting what p_list looks like.
from itertools import permutations
a = ['a','b', 'c']
perm1 = permutations(a, 1)
perm2 = permutations(a, 2)
perm3 = permutations(a, 3)
p_list = []
p_list.extend(list(perm1))
p_list.extend(list(perm2))
p_list.extend(list(perm3))
# p_list = [('a',), ('b',), ('c',), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('a', 'b', 'c'), ('a', 'c', 'b'), ('b', 'a', 'c'), ('b', 'c', 'a'), ('c', 'a', 'b'), ('c', 'b', 'a')]
As you can see, your data structure is not 3rd level: it is only a list of tuples. Now I think it becomes clear that your list comprehension is just iterating over each element inside the tuples, not joining them like:
result = [''.join(n) for n in p_list]
# result = ['a', 'b', 'c', 'ab', 'ac', 'ba', 'bc', 'ca', 'cb', 'abc', 'acb', 'bac', 'bca', 'cab', 'cba']
I have a list of chars chrs = ['A','B','C','D']. How can I generate the outputs like this ['A','AB','ABC','ABCD','B','BC','BCD','C','CD','D'] in python?
Thank you so much!
Try this
s = ''.join(chrs)
res = [s[i: j+1] for i in range(len(s)) for j in range(i, len(s))]
print(res)
Output:
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
A one liner is to use function powerset() from package more_itertools.
Like the following:
from more_itertools import powerset
l = ['A','B','C','D']
list(powerset(l))
# [(), ('A',), ('B',), ('C',), ('D',), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D'), ('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D'), ('A', 'B', 'C', 'D')]
Then you can join it to strings, and sort to get the desired output.
ll = ["".join(x) for x in list(powerset(l))]
sorted(ll)
# ['', 'A', 'AB', 'ABC', 'ABCD', 'ABD', 'AC', 'ACD', 'AD', 'B', 'BC', 'BCD', 'BD', 'C', 'CD', 'D']
You can also easily get read from the empty string by ll[1:]
chrs = ['A','B','C','D']
all_combinations = []
for current_start_index in range(len(chrs)):
for current_combinations_lengh in range(current_start_index, len(chrs)):
all_combinations.append(''.join(list(chrs[current_start_index:current_combinations_lengh+1])))
# Sort, if neccesary
# all_combinations.sort()
# ['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
print(all_combinations)
A simple solution without using any package or module and with basic idea:
chrs=['a','b','c','d']
chrs=''.join(chrs)
a2=[]
i=0
j=1
while(i<len(a) and j<len(a)):
a2.append(a[i:j+1])
j+=1
if j>=len(a):
i+=1
j+=i
a2.append(chrs[-1])
print(a2)
So i have this code below that i created. This code will list every possible combination of a certain value, in this example is "a" "b" "c" "d". If i use this code, the result would be like this: a, aa, ab, ac, ad, aaa, aab, aac, aad, aba, abb, abc, etc. How to simplify this for loop code, so that i can input more values without createing more for loop?
n = "abcd"
for c in n:
print(c)
for c1 in n:
print(c+c1)
for c2 in n:
print(c+c1+c2)
for c3 in n:
print(c+c1+c2+c3)
https://docs.python.org/2/library/itertools.html
Itertools permutations and combinations is what you're after.
itertools.permutations([1, 2, 3])
from itertools import combinations
n = "abcd"
print ([''.join(l) for i in range(len(n)) for l in combinations(n, i+1)])
output:
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'bc', 'bd', 'cd', 'abc', 'abd', 'acd', 'bcd', 'abcd']
edit:
from itertools import combinations_with_replacement
n = "abcd"
comb = []
for i in range(1, len(n)+1):
comb += list(combinations_with_replacement(n, i))
print([''.join(c) for c in comb])
output:
['a', 'b', 'c', 'd', 'aa', 'ab', 'ac', 'ad', 'bb', 'bc', 'bd', 'cc', 'cd', 'dd', 'aaa', 'aab', 'aac', 'aad', 'abb', 'abc', 'abd', 'acc', 'acd', 'add', 'bbb', 'bbc', 'bbd', 'bcc', 'bcd', 'bdd', 'ccc', 'ccd', 'cdd', 'ddd', 'aaaa', 'aaab', 'aaac', 'aaad', 'aabb', 'aabc', 'aabd', 'aacc', 'aacd', 'aadd', 'abbb', 'abbc', 'abbd', 'abcc', 'abcd', 'abdd', 'accc', 'accd', 'acdd', 'addd', 'bbbb', 'bbbc', 'bbbd', 'bbcc', 'bbcd', 'bbdd', 'bccc', 'bccd', 'bcdd', 'bddd', 'cccc', 'cccd', 'ccdd', 'cddd', 'dddd']
To get the same result of 340 elements you can use itertools.product:
product(n, repeat=1)
product(n, repeat=2)
...
product(n, repeat=4)
To print the result you can use the following loop:
from itertools import product
n = "abcd"
for i in range(1, 5):
for prod in product(n, repeat=i):
print(''.join(prod))
To get an extra level you can easily increase the 5 in range. Note: the order of printing is slightly different than in your code.
You can use itertools module to solve your problem. You need combinations_with_replacement function with all possible lengths:
import itertools as it
n = "abcd"
result = []
for l in range(len(n)):
result += list(it.combinations_with_replacement(n, l+1))
print(result)
[('a',), ('b',), ('c',), ('d',), ('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'b'), ('b', 'c'), ('b', 'd'), ('c', 'c'), ('c', 'd'), ('d', 'd'), ('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'a', 'd'), ('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'c'), ('a', 'c', 'd'), ('a', 'd', 'd'), ('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'b', 'd'), ('b', 'c', 'c'), ('b', 'c', 'd'), ('b', 'd', 'd'), ('c', 'c', 'c'), ('c', 'c', 'd'), ('c', 'd', 'd'), ('d', 'd', 'd')]
Say I have the following lists:
l1 = [('a','b','c'),('d','e','f'),('g','h','i'),('j','k','l')]
l2 = ['x','y','z']
l3 = ['m','n']
I want to extract elements from l2 and l3, then append l2[i](i in range(len(l2))) as the first element inside every tuple, and l3[i](i in range(len(l2))) as the last element inside every tuple.
so the result will look like the followings:
l1 = [('x','a','b','c','m'),('x','a','b','c','n'),('y','a','b','c','m'),('y','a','b','c','n'), ('z','a','b','c','m'),('z','a','b','c','n')]
and yes, the len of l1 will be increased.
You can do that with the help of itertools.chain.from_iterable and itertools.product, and get the cartesian product, like this
>>> from itertools import chain, product
>>> from pprint import pprint
>>> pprint([tuple(chain.from_iterable(i)) for i in product(l2, [l1[0]], l3)])
[('x', 'a', 'b', 'c', 'm'),
('x', 'a', 'b', 'c', 'n'),
('y', 'a', 'b', 'c', 'm'),
('y', 'a', 'b', 'c', 'n'),
('z', 'a', 'b', 'c', 'm'),
('z', 'a', 'b', 'c', 'n')]
You are finding the cartesian product between l2, the first element of l1 and l3. Since the result will be a tuple with the element from l2 (a string) and the first element of l1 (a tuple) and an element from l3 (a string), we flatten it with chain.from_iterable.
Let's say we don't flatten the tuples, then this is what you will get
>>> pprint([tuple(items) for items in product(l2, [l1[0]], l3)])
[('x', ('a', 'b', 'c'), 'm'),
('x', ('a', 'b', 'c'), 'n'),
('y', ('a', 'b', 'c'), 'm'),
('y', ('a', 'b', 'c'), 'n'),
('z', ('a', 'b', 'c'), 'm'),
('z', ('a', 'b', 'c'), 'n')]
This is why we use chain.from_iterable and flatten the tuples.
What about playing with zip and list comprehension :
>>> [zip(*i) for i in zip(zip(l2,l2),zip(l1,l1),(l3 for _ in range(2*len(l1))))]
[[('x', ('a', 'b', 'c'), 'm'), ('x', ('a', 'b', 'c'), 'n')], [('y', ('d', 'e', 'f'), 'm'), ('y', ('d', 'e', 'f'), 'n')], [('z', ('g', 'h', 'i'), 'm'), ('z', ('g', 'h', 'i'), 'n')]]