I want to create new lists from one list. This the example list I am working on:
matrixlist = [['Matrix', '1'], ['1', '4', '6'], ['5', '2', '9'], ['Matrix', '2'], ['2', '6'], ['1', '3'], ['8', '6'], ['Matrix', '3'], ['5', '6', '7', '9'], ['1', '4', '2', '3'], ['8', '7', '3', '5'], ['9', '4', '5', '3'], ['Matrix', '4'], ['7', '8'], ['4', '6'], ['2', '3']]
I split them like this with for loop:
matrix1 = [['1', '4', '6'], ['5', '2', '9']]
matrix2 = [['2', '6'], ['1', '3'], ['8', '6']]
matrix3 = [['5', '6', '7', '9'], ['1', '4', '2', '3'], ['8', '7', '3', '5'], ['9', '4', '5', '3']]
matrix4 = [['7', '8'], ['4', '6'], ['2', '3']]
But I want to give the long list to program and it create lists and append the relevant elements in it. Like matrix 1 elements in matrix1 list.
Edit: I can't use any advanced built-in function. I can only use simple ones (like append, pop, reverse, range) and my functions in code.
You can use itertools.groupby:
from itertools import groupby
matrixlist = [['Matrix', '1'], ['1', '4', '6'], ['5', '2', '9'], ['Matrix', '2'], ['2', '6'], ['1', '3'], ['8', '6'], ['Matrix', '3'], ['5', '6', '7', '9'], ['1', '4', '2', '3'], ['8', '7', '3', '5'], ['9', '4', '5', '3'], ['Matrix', '4'], ['7', '8'], ['4', '6'], ['2', '3']]
result = [list(b) for a, b in groupby(matrixlist, key=lambda x:x[0] == 'Matrix') if not a]
Output:
[[['1', '4', '6'], ['5', '2', '9']],
[['2', '6'], ['1', '3'], ['8', '6']],
[['5', '6', '7', '9'], ['1', '4', '2', '3'], ['8', '7', '3', '5'], ['9', '4', '5', '3']],
[['7', '8'], ['4', '6'], ['2', '3']]]
you can do it using list comprehension like below
indx = [i for i, mat in enumerate(matrixlist )if mat[0]=='Matrix']
matrixes = {matrixlist[i][1]: matrixlist[i+1: j] for i, j in zip(indx, indx[1:])}
# access matrix with its id
matrixes["1"]
Related
Edited Question
I've got an inner nested list as shown below.
test_list = [
[['1']],
[['2', '2']],
[['3', '3'], ['4', '4'], ['5', '5'], ['6', '6']],
[['7', '7'], ['8'], ['7'], ['1'], ['7', '7']],
[['7', '7'], ['8'], ['7'], ['7', '7']],
[['2', '2']]]
I'm not looking out to flatten this list per-say. I would rather like to achieve two results.
1)Return a list which discards the outer list for indexes with single item, but keep the nested list for indexes with grouped items. i.e
Expected list output:
new_list = [
['1'],
['2', '2'],
[['3', '3'], ['4', '4'], ['5', '5'], ['6', '6']],
[['7', '7'], ['8'], ['7'], ['1'], ['7', '7']],
[['7', '7'], ['8'], ['7'], ['7', '7']],
['2', '2']]
And when printed looks like:
['1']
['2', '2']
[['3', '3'], ['4', '4'], ['5', '5'], ['6', '6']]
[['7', '7'], ['8'], ['7'], ['1'], ['7', '7']]
[['7', '7'], ['8'], ['7'], ['7', '7']]
['2', '2']
2)Return a new unique list which would look like the new_list variable expressed below.
new_list = [
['1'],
['2'],
['3', '4', '5', '6'],
['7', '8', '7', '1', '7'],
['7', '8', '7', '7'],
['2']]
i.e each item in the new list printed out as:
['1']
['2']
['3', '4', '5', '6']
['7', '8', '7', '1', '7']
['7', '8', '7', '7']
['2']
Thanks.
PS: Sorry for the total re-edit, I totally misrepresented the expected result.
You can use a simple test on the sublists length in a list comprehension:
out = [l[0] if len(l)==1 else l for l in test_list]
output:
[['1'],
['2', '2'],
[['3', '3'], ['4', '4'], ['5', '5'], ['6', '6']],
[['7', '7'], ['8'], ['7'], ['1'], ['7', '7']],
[['7', '7'], ['8'], ['7'], ['7', '7']],
['2', '2']]
If you really want to print:
for l in test_list:
print(l[0] if len(l)==1 else l)
['1']
['2', '2']
[['3', '3'], ['4', '4'], ['5', '5'], ['6', '6']]
[['7', '7'], ['8'], ['7'], ['1'], ['7', '7']]
[['7', '7'], ['8'], ['7'], ['7', '7']]
['2', '2']
edited question
you need a nested list comprehension:
[[x[0] for x in l] for l in test_list]
Output:
[['1'],
['2'],
['3', '4', '5', '6'],
['7', '8', '7', '1', '7'],
['7', '8', '7', '7'],
['2']]
If you struggle with understanding list comprehension, especially the nested list comprehension, you can break it down with the usual for loop and if's conditional.
new_list = []
for each_index in test_list:
if len(each_index) == 1:
new_list.append(each_index[0])
else:
new_list.append(each_index)
print(new_list)
And the second answer with the nested list comprehension translates to:
new_list = []
for each_index in test_list:
test = []
for each_item in each_index:
test.append(each_item[0])
new_list.append(test)
print(new_list)
NOTE:
The list comprehension answer given by #mozway is more concise, but when I want to properly understand the flow of list comprehension, a good practice is to break it down like this so that i avoid just copying and pasting, but leave with a better understanding.
mat = [['1', '2', '3', '4', '5'],
['6', '7', '8', '9', '10'],
['11', '12', '13', '14', '15']]
Suppose, I have this vector of vectors.
Say, I need to extract 2nd column of each row, convert them into binary, and then create a vector of them.
Is it possible to do it without using NumPy?
Use zip for transpose list and make loop with enumerate and filter by id with bin().
mat = [['1', '2', '3', '4', '5'],
['6', '7', '8', '9', '10'],
['11', '12', '13', '14', '15']]
vec = [[bin(int(r)) for r in row] for idx, row in enumerate(zip(*mat)) if idx == 1][0]
print(vec) # ['0b10', '0b111', '0b1100']
Yes. This is achievable with the following code :
mat = [['1', '2', '3', '4', '5'],
['6', '7', '8', '9', '10'],
['11', '12', '13', '14', '15']]
def decimalToBinary(n):
return bin(n).replace("0b", "")
new_vect = []
for m in mat:
m = int(m[1])
new_vect.append(decimalToBinary(m))
print (new_vect)
Hope this is expected
['10', '111', '1100']
I have a list of lists of strings:
listBefore = [['4', '5', '1', '1'],
['4', '6', '1', '1'],
['4', '7', '8', '1'],
['1', '2', '1', '1'],
['2', '3', '1', '1'],
['7', '8', '1', '1'],
['7', '9', '1', '1'],
['2', '4', '3', '1']]
and I would like to add a counter/index in the middle of each list so that the list looks like:
listAfter = [['4', '5', '1', '1', '1'],
['4', '6', '2', '1', '1'],
['4', '7', '3', '8', '1'],
['1', '2', '4', '1', '1'],
['2', '3', '5', '1', '1'],
['7', '8', '6', '1', '1'],
['7', '9', '7', '1', '1'],
['2', '4', '8', '3', '1']]
What would be the easiest way to do so? I could probably loop over the lists and add the index, but is there a cleaner way to do so?
Cheers,
Kate
Edit:
The code I wrote works for me:
item = 1
for list in listBefore:
list.insert(2,str(item))
item = item + 1
print listBefore
I was wondering if there is another way to do so more efficiently or in one step.
Iterate over the parent list with enumerate() to get counter (used as i in the below example) along with list element. In the sublist, insert the i at the middle of sublist using list.insert(index, value) method.
Note: The value of counter i.e. i will be of int type, so you have to explicitly type cast it to str as str(i)before inserting. Below is the sample code:
for i, sub_list in enumerate(my_list, 1): # Here my_list is the list mentioned in question as 'listBefore'
sub_list.insert(len(sub_list)/2, str(i))
# Value of 'my_list'
# [['4', '5', '1', '1', '1'],
# ['4', '6', '2', '1', '1'],
# ['4', '7', '3', '8', '1'],
# ['1', '2', '4', '1', '1'],
# ['2', '3', '5', '1', '1'],
# ['7', '8', '6', '1', '1'],
# ['7', '9', '7', '1', '1'],
# ['2', '4', '8', '3', '1']]
You can perform this with a list comprehension
listAfter = [listBefore[i][:len(listBefore[i])/2] + [str(i+1)] + listBefore[i][len(listBefore[i])/2:] for i in range(len(listBefore))]
You should learn about enumerate, it lets you iterate over the list with two iterators - one (str_list in this case) holds the current item in the list, and the other (i`) holds it's index in the list.
for i,str_list in enumerate(listBefore):
listBefore[i] = str_list[:len(str_list)//2] + [str(i+1)] + str_list[len(str_list)//2:]
>>> data = [['4', '5', '1', '1'],
['4', '6', '1', '1'],
['4', '7', '8', '1'],
['1', '2', '1', '1'],
['2', '3', '1', '1'],
['7', '8', '1', '1'],
['7', '9', '1', '1'],
['2', '4', '3', '1']]
>>> print [row[:len(row)//2] + [str(i)] + row[len(row)//2:]
for i, row in enumerate(data, start=1)]
[['4', '5', '1', '1', '1'],
['4', '6', '2', '1', '1'],
['4', '7', '3', '8', '1'],
['1', '2', '4', '1', '1'],
['2', '3', '5', '1', '1'],
['7', '8', '6', '1', '1'],
['7', '9', '7', '1', '1'],
['2', '4', '8', '3', '1']]
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 6 years ago.
I have two nested for loops and two lists, I want one of tle list to re-initialize after one iteration of inner loop.
def test():
i = ['1','5','9','3','6','4']
for x in xrange(0,len(i)):
j = ['6', '7', '9', '3']
newi = i
for y in xrange(0,len(j)):
newi[x] = j[y]
print "i", i
print "end of one iteration on finner loop"
print "newi", newi
test()
Its a dummy code, I want a clean new instance of newi to be that of i after one iteration of inner loop, currently it preserver the value of inner loop
current output:
i ['6', '5', '9', '3', '6', '4']
i ['7', '5', '9', '3', '6', '4']
i ['9', '5', '9', '3', '6', '4']
i ['3', '5', '9', '3', '6', '4']
end of one iteration on inner loop
newi ['3', '5', '9', '3', '6', '4']
i ['3', '6', '9', '3', '6', '4']
i ['3', '7', '9', '3', '6', '4']
i ['3', '9', '9', '3', '6', '4']
i ['3', '3', '9', '3', '6', '4']
end of one iteration on inner loop
newi ['3', '3', '9', '3', '6', '4']
i ['3', '3', '6', '3', '6', '4']
i ['3', '3', '7', '3', '6', '4']
i ['3', '3', '9', '3', '6', '4']
i ['3', '3', '3', '3', '6', '4']
end of one iteration on inner loop
newi ['3', '3', '3', '3', '6', '4']
i ['3', '3', '3', '6', '6', '4']
i ['3', '3', '3', '7', '6', '4']
i ['3', '3', '3', '9', '6', '4']
i ['3', '3', '3', '3', '6', '4']
end of one iteration on inner loop
newi ['3', '3', '3', '3', '6', '4']
i ['3', '3', '3', '3', '6', '4']
i ['3', '3', '3', '3', '7', '4']
i ['3', '3', '3', '3', '9', '4']
i ['3', '3', '3', '3', '3', '4']
end of one iteration on inner loop
newi ['3', '3', '3', '3', '3', '4']
i ['3', '3', '3', '3', '3', '6']
i ['3', '3', '3', '3', '3', '7']
i ['3', '3', '3', '3', '3', '9']
i ['3', '3', '3', '3', '3', '3']
end of one iteration on inner loop
newi ['3', '3', '3', '3', '3', '3']
Instead of:
newi = i
replace with:
newi = list(i) # list(i) creates another copy i
I know that you can swap 2 single indexes in Python
r = ['1', '2', '3', '4', '5', '6', '7', '8']
r[2], r[4] = r[4], r[2]
output:
['1', '2', '5', '4', '3', '6', '7', '8']
But why can't you swap 2 slices of indexes in python?
r = ['1', '2', '3', '4', '5', '6', '7', '8']
I want to swap the numbers 3 + 4 with 5 + 6 + 7 in r:
r[2:4], r[4:7] = r[4:7], r[2:4]
output:
['1', '2', '5', '6', '3', '4', '7', '8']
expected output:
['1', '2', '5', '6', '7', '3', '4', '8']
What did I wrong?
output:
The slicing is working as it should. You are replacing slices of different lengths. r[2:4] is two items, and r[4:7] is three items.
>>> r = ['1', '2', '3', '4', '5', '6', '7', '8']
>>> r[2:4]
['3', '4']
>>> r[4:7]
['5', '6', '7']
So when ['3', '4'] is replaced, it can only fit ['5', '6'], and when ['5', '6', '7'] is replaced, it only gets ['3', '4']. So you have ['1', '2',, then the next two elements are the first two elements from ['5', '6', '7'] which is just ['5', '6', then the two elements from ['3', '4' go next, then the remaining '7', '8'].
If you want to replace the slices, you have to start slices at the right places and allocate an appropriate size in the array for each slice:
>>> r = ['1', '2', '3', '4', '5', '6', '7', '8']
>>> r[2:5], r[5:7] = r[4:7], r[2:4]
>>> r
['1', '2', '5', '6', '7', '3', '4', '8']
old index: 4 5 6 2 3
new index: 2 3 4 5 6
Think of this:
r[2:4], r[4:7] = r[4:7], r[2:4]
as similar to this:
original_r = list(r)
r[2:4] = original_r[4:7]
r[4:7] = original_r[2:4]
So, by the time it gets to the third line of that, the 4th element isn't what you think it is anymore... You replaced '3', '4' with '5', '6', '7', and now the [4:7] slice starts with that '7'.
>>> r = ['1', '2', '3', '4', '5', '6', '7', '8']
>>> r[2:5], r[5:7] = r[4:7], r[2:4]
>>> r
['1', '2', '5', '6', '7', '3', '4', '8']
In your code:
>>> r[2:4], r[4:7] = r[4:7], r[2:4]
You are assigning r[4:7] which have 3 elements to r[2:4] which have only 2.
In the code I posted:
>>> >>> r[2:5], r[5:7] = r[4:7], r[2:4]
r[4:7] which is ['5', '6', '7'], replaces
r[2:5] which is ['3', '4', '5']
r resulting in ['1', '2', '5', '6', '7', '6', '7', '8']
and then:
r[2:4] which was ['3', '4'], replaces
r[5:7] which is ['6', '7']
So final result being:
['1', '2', '5', '6', '7', '3', '4', '8']