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']
Related
I am trying to implement insertion sort using python. Below is my code:
import numpy as np
N=int(input())
A=input().split()
#A=[int(x) for x in input().split()]
B_sorted=A.copy()
C= A.copy()
def inssort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i-1
while (j >=0 and key < arr[j]):
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
inssort(B_sorted)
for i in range(0,len(A)):
for j in range(0,len(A)):
if A[i]==B_sorted[j]:
C[i]=j+1
break
j=j+1
i=i+1
for x in B_sorted:
print (x, "",end="")
My code works for the following set of entries:
[9,8,7,...,2,1]
[20,19,...,12,11]
[20,19,...,11,10]
but it doesn't work for following
[10,9,8,...,2,1]
I don't understand what exactly is the issue here.
I tried to go to the detail by printing the output at every loop:
10 9 8 7 6 5 4 3 2 1
['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']
['10', '8', '9', '7', '6', '5', '4', '3', '2', '1']
['10', '7', '8', '9', '6', '5', '4', '3', '2', '1']
['10', '6', '7', '8', '9', '5', '4', '3', '2', '1']
['10', '5', '6', '7', '8', '9', '4', '3', '2', '1']
['10', '4', '5', '6', '7', '8', '9', '3', '2', '1']
['10', '3', '4', '5', '6', '7', '8', '9', '2', '1']
['10', '2', '3', '4', '5', '6', '7', '8', '9', '1']
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
Looks like for some reason at the first iteration j is not taking the value 0 for this particular sequence. As I mentioned before, it works perfectly for a lot of other sequences.
Kindly help.
n=10
fun=list(map(lambda x:[j for j in range(x)],n))
print(fun)
expected output is:
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
# using map (map works on an iterable)
n=10
fun=lambda x: (range(x)) # remember this is a function (so call it)
fun=list(map(str, fun(n)))
print(fun)
# directly
n=10
fun=list(map(str, (range(n))))
print(fun)
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
Python docs for reference:
map(): https://docs.python.org/3/library/functions.html#map
range(): https://docs.python.org/3/library/functions.html#func-range
lambda(): https://docs.python.org/3/library/ast.html?highlight=lambda#ast.Lambda
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']]
I'm trying to draw histrogram based of my value
x = ['3', '1', '4', '1', '5', '9', '2', '6', '5', '3', '5',
'2', '3', '4', '5', '6', '4', '2', '0', '1', '9', '8',
'8', '8', '8', '8', '9', '3', '8', '0', '9', '5', '2',
'5', '7', '2', '0', '1', '0', '6', '5']
x_num = [int(i) for i in x]
key = '0123456789'
for i in key:
print(i," count =>",x.count(i))
plt.hist(x_num, bins=[0,1,2,3,4,5,6,7,8,9])
The last 2 numbers "8, 9" bin should have distribution count of 6 , 4
But in histogram it combine 8 and 9 and get value of 10 instead of separate them. Total number of bin should be 10 => but it only giving me graph of 9..
How could I separate them and break 8 and 9 ?
import matplotlib.pyplot as plt
x = ['3', '1', '4', '1', '5', '9', '2', '6', '5', '3', '5',
'2', '3', '4', '5', '6', '4', '2', '0', '1', '9', '8',
'8', '8', '8', '8', '9', '3', '8', '0', '9', '5', '2',
'5', '7', '2', '0', '1', '0', '6', '5']
x_num = [int(i) for i in x]
key = '0123456789'
for i in key:
print(i, " count =>", x.count(i))
plt.hist(x_num, bins=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10])
plt.show()
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