How to split/slice a list in Python - python

I saw this code in w3resource:
C = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']
def list_slice(S, step):
return [S[i::step] for i in range(step)]
print(list_slice(C,3))
Output :[['a', 'd', 'g', 'j', 'm'], ['b', 'e', 'h', 'k', 'n'], ['c', 'f', 'i', 'l']]
I tried it without list comprehension and a function:
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']
step = int(input("Step of every element: "))
for i in range(step):
print(letters[i::step])
Output:
['a', 'd', 'g', 'j', 'm']
['b', 'e', 'h', 'k', 'n']
['c', 'f', 'i', 'l']
is it possible to make my output like this [['a', 'd', 'g', 'j', 'm'], ['b', 'e', 'h', 'k', 'n'], ['c', 'f', 'i', 'l']] without using list comprehension and without making another variable with an empty list?

not a list comprehension solution, but since you want an element having certain distance/step in the list to be in the same list, then you can see that those element index share single property altogether which have the same remainder to the step value, using this approach you can save those value for that index remainder in a key-value pair of dict and in result you can take the values which are nonempty.
C = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n']
def func(lis, slic):
res = {i:[] for i in range(len(lis)//slic)}
for i in range(len(lis)):
res[i%slic].append(lis[i])
return [i for i in res.values() if i!=[]]
print(func(C, 3))
# Output :[['a', 'd', 'g', 'j', 'm'], ['b', 'e', 'h', 'k', 'n'], ['c', 'f', 'i', 'l']]

Related

Python - Creating permutations with output array index constraints

I want to create all possible permutations for an array in which each element can only occur once, with constraints on the element array index position.
ID = ["A","B","C","D","E","F","G","H","I","J"]
I want to create all possible permutations of the original_array, however the positions of each element are restricted to index positions given by:
ID = ["A","B","C","D","E","F","G","H","I","J"]
Index_Options=[]
for i in range(len(ID)):
List1=[]
distance=3
value = i - distance
for j in range((int(distance)*2)):
if value < 0 or value > len(ID):
print("Disregard") #Outside acceptable distance range
else:
List1.append(value)
value=value+1
Index_Options.append(List1)
print(Index_Options)
#Index_Options gives the possible index positions for each element. ie "A" can occur in only index positions 0,1,2, "B" can occur in only index positions 0,1,2,3 ect.
I'm just struggling on how to then use this information to create all the output permutations.
Any help would be appreciated
You can use a recursive generator function to build the combinations. Instead of generating all possible permutations from ID and then filtering based on Index_Options, it is much more efficient to produce a cartesian product of ID by directly traversing Index_Options:
ID = ["A","B","C","D","E","F","G","H","I","J"]
def combos(d, c = [], s = []):
if not d:
yield c
else:
for i in filter(lambda x:x not in s and x < len(ID), d[0]):
yield from combos(d[1:], c=c+[ID[i]], s=s+[i])
print(list(combos(Index_Options)))
Output (first ten combinations produced):
[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'I'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'I', 'H', 'J'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'I', 'J', 'H'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'J', 'H', 'I'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'J', 'I', 'H'], ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'G', 'I', 'J'], ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'G', 'J', 'I'], ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'I', 'G', 'J'], ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'I', 'J', 'G']]
You can use itertools.permutations to create all the possible permutations and then create new list with a check if all the letters are in the correct position
permutations = [p for p in itertools.permutations(ID, len(ID)) if all(i in Index_Options[ID.index(x)] for i, x in enumerate(p))]

return list pair (print out) from 2 list of same length

I have 2 lists (x and y) and I want to output in x, y (just the print out). May I know how to do it? Do I need a loop to loop through each item in the x and y list?
input :
x = [['A', 'B'], ['C', 'D'], ['F', 'G']]
y = [['L', 'M'], ['J', 'K'], ['O', 'P', 'Q']]
output :
x, y format
['A', 'B'] ['L', 'M']
['C', 'D'] ['J', 'K']
['F', 'G'] ['O', 'P', 'Q']
The closest I got is as below :
for row in x:
n = []
for loop in y :
for x in loop :
n.append(x)
print(' '.join(row).strip().split()) , n
Output :
['A', 'B'] ['L', 'M']
['A', 'B'] ['L', 'M', 'J', 'K']
['A', 'B'] ['L', 'M', 'J', 'K', 'O', 'P', 'Q']
['C', 'D'] ['L', 'M']
['C', 'D'] ['L', 'M', 'J', 'K']
['C', 'D'] ['L', 'M', 'J', 'K', 'O', 'P', 'Q']
['F', 'G'] ['L', 'M']
['F', 'G'] ['L', 'M', 'J', 'K']
['F', 'G'] ['L', 'M', 'J', 'K', 'O', 'P', 'Q']
You can use zip to make tuples of elements of your lists:
list(zip(x, y))
Produces:
[(['A', 'B'], ['L', 'M']),
(['C', 'D'], ['J', 'K']),
(['F', 'G'], ['O', 'P', 'Q'])]
The resulting list is, in this example, of length 3. The first element is:
>>> list(zip(x, y))[0]
(['A', 'B'], ['L', 'M'])
In order to print the tuples with a space in between:
for a, b in zip(x, y):
print(f'{a} {b}')
Output:
['A', 'B'] ['L', 'M']
['C', 'D'] ['J', 'K']
['F', 'G'] ['O', 'P', 'Q']

Getting the variable from a for loop?

Hi I am a newbie in python and there is a variable that I would like to carry over outside a for loop, the code is below:
positive_slopes=[[rows[p - q][q]
for q in range(max(p-column_length+1,0), min(p+1, row_length))]
for p in range(column_length + row_length - 1)]
In this case I would like to get all values of [p-q] and [q] but I don't really know how to manipulate this code,it essentially breaks when I try to change something.
I tried using a normal for loop but does not give the same result as the code above.The for loop code I tried to use is:
for p in range(column_length + row_length - 1):
for q in range(max(p-column_length+1,0), min(p+1, row_length)):
positive_slopes.append(rows[p - q][q])
This does not quite give the same results with the list comprehension code. This gives an output of:
['e', 'a', 'a', 'g', 'l', 'h', 'r', 'o', 'l', 'a', 'i', 'h', 'h', 'e', 'e', 'i', 'a', 'e', 'l', 'h', 'h', 'h', 'i', 'y', 'l', 'o', 'o', 'h', 'l', 'a', 'o', 'l', 'a', 'h', 'h', 'e', 'y', 'o', 'u', 'a', 'l', 'i', 'y', 'l', 'a', 'u', 'l', 'h', 'o']
The list comprehension gives me this:
[['e'], ['a', 'a'], ['g', 'l', 'h'], ['r', 'o', 'l', 'a'], ['i', 'h', 'h', 'e', 'e'], ['i', 'a', 'e', 'l', 'h', 'h'], ['h', 'i', 'y', 'l', 'o', 'o', 'h'], ['l', 'a', 'o', 'l', 'a', 'h'], ['h', 'e', 'y', 'o', 'u'], ['a', 'l', 'i', 'y'], ['l', 'a', 'u'], ['l', 'h'], ['o']]
The elements of both outputs are the same however I would like the for loop to group the letters like the list comprehension did. What am I missing in my for loop to give me the same output. Any help would be gladly appreciated!
Your edited code should be something like:
for p in range(column_length + row_length - 1):
tempList = []
for q in range(max(p-column_length+1,0), min(p+1, row_length)):
tempList.append(rows[p - q][q])
positive_slopes.append(tempList)

numpy reshape and tile

I am trying to convert a vector from A-L to something like this with pandas and numpy built in functions without loops (tile, repeat and reshape). But I cannot wrap my head around
0 1 2 3 4 5 6 7 8 9 10 11
0 A A A A E E E E I I I I
1 B B B B F F F F J J J J
2 C C C C G G G G K K K K
3 D D D D H H H H L L L L
4 A A A A E E E E I I I I
5 B B B B F F F F J J J J
6 C C C C G G G G K K K K
7 D D D D H H H H L L L L
Do you have any ideas how I could do that without loops ?
what I have tried so far:
a = np.array(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'])
b = a.reshape(3,4)
np.repeat(b, 4).reshape(4,12)
gives me:
array([['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C'],
['D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F'],
['G', 'G', 'G', 'G', 'H', 'H', 'H', 'H', 'I', 'I', 'I', 'I'],
['J', 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'L', 'L', 'L', 'L']],
dtype='<U1')
EDIT: Some background. Depending on the number of samples and the layout we choose. A machine, creates plates (like in this image). We can do consecutive operations (add more chemicals etc.) and based on the previous layout, unique combinations are obtained. Afterwards the machine measures e.g. concentration in each well and I would like to link the output to the conditions in each well. Because the machine can measure e.g. concentration after each step, a lot of data can be generated and I am trying to find a generic solution without too many loops.
You could use:
>>> import numpy as np
>>> x = np.array(list('abcdefghijkl'.upper())) # your "vector"
>>> np.repeat(np.tile(x.reshape(-1, 4), 2).T, 4, axis=1)
array([['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L'],
['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L']],
dtype='<U1')
It first reshapes it so that you have 4 characters in each column, then duplicates them. Then you transpose it so you have the correct rows/columns and finally you just repeat every character 4 times.
Step-by-step it looks like this:
>>> import pandas as pd
>>> x
array(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'],
dtype='<U1')
>>> x.reshape(-1, 4)
array([['A', 'B', 'C', 'D'],
['E', 'F', 'G', 'H'],
['I', 'J', 'K', 'L']],
dtype='<U1')
>>> np.tile(_, 2)
array([['A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'],
['E', 'F', 'G', 'H', 'E', 'F', 'G', 'H'],
['I', 'J', 'K', 'L', 'I', 'J', 'K', 'L']],
dtype='<U1')
>>> _.T
array([['A', 'E', 'I'],
['B', 'F', 'J'],
['C', 'G', 'K'],
['D', 'H', 'L'],
['A', 'E', 'I'],
['B', 'F', 'J'],
['C', 'G', 'K'],
['D', 'H', 'L']],
dtype='<U1')
>>> np.repeat(_, 4, axis=1)
array([['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L'],
['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L']],
dtype='<U1')
>>> pd.DataFrame(_)
0 1 2 3 4 5 6 7 8 9 10 11
0 A A A A E E E E I I I I
1 B B B B F F F F J J J J
2 C C C C G G G G K K K K
3 D D D D H H H H L L L L
4 A A A A E E E E I I I I
5 B B B B F F F F J J J J
6 C C C C G G G G K K K K
7 D D D D H H H H L L L L
a = np.array(list("ABCDEFGHIJKL"))
a
# array(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'],
# dtype='<U1')
np.repeat(np.tile(a.reshape(3,4), 2).T, 4, axis=1)
#array([['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
# ['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
# ['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
# ['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L'],
# ['A', 'A', 'A', 'A', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I'],
# ['B', 'B', 'B', 'B', 'F', 'F', 'F', 'F', 'J', 'J', 'J', 'J'],
# ['C', 'C', 'C', 'C', 'G', 'G', 'G', 'G', 'K', 'K', 'K', 'K'],
# ['D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'L', 'L', 'L', 'L']],
# dtype='<U1')

Python: Iterating through the columns in a list of list to find the palindromes

Here I have a word list as:
[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
And I have to display all the palindromes in this list which are in rows as well as columns.
I have coded to find all the palindromes in the rows. But cannot implement a method to find the palindromes in the columns.
Here is my code so far:
result_1=""
if len(palindrome)==len_line_str:
for row in range(len(palindrome)):
for horizontal_line in range(len(palindrome[row])):
if ''.join(palindrome[row])==''.join(reversed(palindrome[row])):
result_1=''.join(palindrome[row])+" is a palindrome starting at ["+str(row)+"]["+str(row)+"] and is a row in the table"
print(result_1)
Which will display the output:
rotor is a palindrome starting at [0][0] and is a row in the table
Where "rotor" is a palindrome.
I need a method to get the palindromes in the columns which are:
"refer", "tenet", "radar"
Any help is much appreciated. Thanks in advance!
You can use zip to transpose your lists:
>>> t = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
>>> list(zip(*t))
[('r', 'e', 'f', 'e', 'r'), ('o', 'v', 'i', 'n', 'a'), ('t', 'e', 'n', 'e', 't'), ('o', 'i', 'e', 't', 'e'), ('r', 'a', 'd', 'a', 'r')]
Your columns are now rows, and you can apply the same method than before. If you just need the words, you can use list comprehensions:
>>> rows = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
>>> [''.join(row) for row in rows if row[::-1] == row ]
['rotor']
>>> [''.join(column) for column in zip(*rows) if column[::-1] == column ]
['refer', 'tenet', 'radar']
This will do the job:
palindrome=[['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
n=len(palindrome)
for col in range(len(palindrome[0])):
col_word=[palindrome[i][col] for i in range(n)]
if ''.join(col_word)==''.join(reversed(col_word)):
result=''.join(col_word)+" is a palindrome starting at ["+str(col)+"] and is a col in the table"
print(result)
This prints
refer is a palindrome starting at [0] and is a col in the table
tenet is a palindrome starting at [2] and is a col in the table
radar is a palindrome starting at [4] and is a col in the table
Basically, in order to access the words in the column, you can do
col_word=[palindrome[i][col] for i in range(n)]
This fixes the column and iterates over the rows. The rest of the code is structures similarly to yours.
​
I saw you did not want to use Zip (which I would recommend using):
Alternative answer:
list_ = [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
You can get the palindromes (rows) by checking each list with the reversed list [::-1]:
[i==i[::-1] for i in list_]
# prints [True, False, False, False, False]
And get the palindromes (columns) by 1. create the column list (called list_2 below) with a list comprehension and 2. same principle as above:
list_2 = [[i[ind] for i in list_] for ind in range(len(list_))]
[i==i[::-1] for i in list_2]
# prints [True, False, True, False, True]
Update
If you want the answers directly you can do:
[i for i in list_ if i==i[::-1]]
# prints [['r', 'o', 't', 'o', 'r']]
# and list_2: [['r', 'e', 'f', 'e', 'r'],['t', 'e', 'n', 'e', 't'],['r', 'a', 'd', 'a', 'r']]
There are a lot of ways to do it. I will take as example your code because of your effort on it
Another alternative following your code, is creating the columns in another list and check wich of them are palindromes:
palindrome = [['r', 'o', 't', 'o', 'r'],
['e', 'v', 'e', 'i', 'a'],
['f', 'i', 'n', 'e', 'd'],
['e', 'n', 'e', 't', 'a'],
['r', 'a', 't', 'e', 'r']]
len_line_str = 5
result_1=""
def is_pal(string):
return string == reversed(string)
colums = []
if len(palindrome)==len_line_str:
for row in range(len(palindrome)):
vertical = []
if ''.join(palindrome[row])==''.join(reversed(palindrome[row])):
result_1+=''.join(palindrome[row])+" is a palindrome starting at ["+str(0)+"]["+str(row)+"] and is a row in the table. " + "\n"
for horizontal_line in range(len(palindrome[row])):
if(len_line_str-1 > horizontal_line):
vertical += [palindrome[horizontal_line][row]]
else:
vertical += [palindrome[horizontal_line][row]]
colums += [(vertical,row)]
for word in colums:
if ''.join(word[0])==''.join(reversed(word[0])):
result_1+=''.join(word[0])+" is a palindrome starting at ["+str(0)+"]["+str(word[1])+"] and is a column in the table" + "\n"
print(result_1)
This should work. First loop iterates through the list s and the second loop iterates through each list.
Assuming s is the name of the list- [['r', 'o', 't', 'o', 'r'], ['e', 'v', 'e', 'i', 'a'], ['f', 'i', 'n', 'e', 'd'], ['e', 'n', 'e', 't', 'a'], ['r', 'a', 't', 'e', 'r']]
for i in xrange(0,len(s),1):
str = ""
for j in s:
str = str + j[i]
print str
if str == str[::-1]:
print str," is a pallindrome - column", i
else:
print str," is not a pallindrome - column", i
There is no column wise traversal in Python. One hacky way you can follow is to perform transpose operation on your input matrix. Below is a simple way to implement transpose using list comprehensions.
def transpose(matrix):
if not matrix:
return []
return [[row[i] for row in matrix] for i in range(len(matrix[0]))]
Your same logic should work once modify your input using transpose.
Hope this helps!!

Categories