Confusion with the index method of a list in python. - python

How is this possible?
list = [0, 0, 0, 0]
for i in list:
print list.index(i),
list[ list.index(i) ] += 1
This prints: 0 1 2 3 (which is understandable)
list = [1, 4, 5, 2]
for i in list:
print list.index(i),
list[ list.index(i) ] += 1
This prints: 0 1 1 0

list.index(i) returns the first index where the value i is found in the list.
> i = 1
prints: 0
list[0] = 1+1 = 2 -> list = [2,4,5,2]
> i = 4
prints: 1
list[1] = 4+1 = 5 -> list = [2,5,5,2]
> i = 5
prints: 1 #because that's where 5 is first found in the list
list[1] = 5+1 = 6 -> list = [2,6,5,2]
> i = 2
prints: 0 #because that's where 2 is first found in the list
list[0] = 2+1 = 3 -> list = [3,6,5,2]

If you modify your loop to print out more about what's happening, you can see for yourself:
list = [0, 0, 0, 0]
for i in list:
print i, 'found at', list.index(i), 'in', list
list [ list.index(i) ] += 1
print "list'", list
0 found at 0 in [0, 0, 0, 0]
list' [1, 0, 0, 0]
0 found at 1 in [1, 0, 0, 0]
list' [1, 1, 0, 0]
0 found at 2 in [1, 1, 0, 0]
list' [1, 1, 1, 0]
0 found at 3 in [1, 1, 1, 0]
list' [1, 1, 1, 1]
And...
list = [1, 4, 5, 2]
for i in list:
print i, 'found at', list.index(i), 'in', list
list [ list.index(i) ] += 1
print "list'", list
1 found at 0 in [1, 4, 5, 2]
list' [2, 4, 5, 2]
4 found at 1 in [2, 4, 5, 2]
list' [2, 5, 5, 2]
5 found at 1 in [2, 5, 5, 2]
list' [2, 6, 5, 2]
2 found at 0 in [2, 6, 5, 2]
list' [3, 6, 5, 2]

Related

Replacing items in a list with items from another list in python

list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
Would it be possible to replace each 3 in list1 with an element from list2? If so, how would I go about doing this?
You could create an iterator for list2, and then call next() to replace the next element in list1 that is equal to 3, while using a list comprehension.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l2 = iter(list2)
out = [i if i!=3 else next(l2) for i in list1]
print(out)
Output:
[0, 4, 1, 1, 0, 2, 1, 0, 4, 1, 0, 2, 5]
We can use two pointers to keep track of list1 and list2. Then we replace each 3 in list1 with a value from list2 even it is not 0 until traversing to the end of any of the list.
list1 = [3, 4, 1, 1, 0, 3, 1, 0, 4, 3, 3, 2, 3]
list2 = [0, 0, 0, 0, 0]
x = 0
y = 0
while x < len(list1) and y < len(list2):
if list1[x] == 3:
list1[x] = list2[y]
y += 1
x += 1
print(list1)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
l1_num = 3 # number to be replaced in list 1
l2_num = 0 # number to be replaced in list 2
n = min(list1.count(l1_num),list2.count(l2_num))
for i in range(n):
list1[list1.index(l1_num)] = l2_num
list2[list2.index(l2_num)] = l1_num
#list1 = [0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]
#list2 = [3, 2, 1, 3, 5]
we can use for in and store our needed short list value out of the loop. like the following code will replace all 3 in list1 with zeros and all 0 in list2 with 3s in list1:
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,1,0,3,0]
#shortlistval will be used to store short list desired value
shortlistVal =1;#default val is just for declaration
for i1 in range(0, len(list1)):
for i in range(0,len(list2)):
if list1[i1] ==3 and list2[i] == 0:
shortlistVal=list2[i]
list2[i]=list1[i1]
if list1[i1]==3:
list1[i1]= shortlistVal
print(list1)
print(list2)
Output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 0, 0, 2, 0]
[3, 1, 3, 3, 3]
Use two for loops and replace each 3 for 0 s in list 2.
list1 = [3,4,1,1,0,3,1,0,4,3,3,2,3]
list2 = [0,2,1,0,5]
for i in range(list2.count(0)):
for x in list1:
if x == 3: list1[list1.index(x)] = 0; break
print(list1)
output:
[0, 4, 1, 1, 0, 0, 1, 0, 4, 3, 3, 2, 3]

recursive calling to print list of numbers

I'm trying to sort an array and print the output recursively until the array is = [0,0,0,0,0] but it only prints [3,2,1,0,0] ,,,,, this is what i wrote can you help to fix this isuee ,, still learning
the answer should be
[4 3 2 1 0 0]
[3 2 1 0 0 0]
[2 1 0 0 0 0]
[1 0 0 0 0 0]
[0 0 0 0 0 0]
numbers=[5,4,3,2,1,1]
numbers.sort()
numbers.sort(reverse=True)
print('List sorted: ', numbers)
def list_arrays(numb):
level=numbers[0]
if len(numbers)-1 < level:
return 0
else:
numbers.pop(0);
print(numbers)
for i in range(len(numbers)):
numbers[i] -= 1
print(numbers)
#list_arrays(numbers)
if __name__=='__main__':
list_arrays(numbers)
You have a number of problems here. First, you defined a function, but you never called the function. That's why nothing printed.
Second, you don't need "sort" immediately followed by "sort(reverse)".
Third, I don't know what you were attempting by checking the level. That doesn't seem to be related to your problem.
Fourth, you're subtracting 1 from every number, but you should only be subtracting 1 if the number is greater than 0.
Finally, you're only subtracting once. You need to repeat it until all the numbers are zero.
numbers=[5,4,3,2,1,1]
numbers.sort(reverse=True)
print('List sorted: ', numbers)
def list_arrays(numb):
while any(numb):
for i in range(len(numb)):
if numb[i]:
numb[i] -= 1
print(numb)
list_arrays(numbers)
In most cases, rather than modify the list in place, I would suggest creating a new list during each loop, but for this simple assignment, this will work.
To remove the zeros, you really do want to create a new list, not modify in place.
numbers=[5,4,3,2,1,1]
numbers.sort(reverse=True)
print('List sorted: ', numbers)
def list_arrays(numb):
while numb:
new = []
for v in numb:
if v > 1:
new.append(v-1)
numb = new
print(numb)
list_arrays(numbers)
Or even:
numbers=[5,4,3,2,1,1]
numbers.sort(reverse=True)
print('List sorted: ', numbers)
def list_arrays(numb):
while numb:
numb = [v-1 for v in numb if v>1]
print(numb)
list_arrays(numbers)
In another comment you asked to remove all zeroes. Perhaps this is the solution you are looking for -
def run(t):
while(t):
yield t
t = [x - 1 for x in t if x > 1]
mylist = [5,4,3,2,1,1]
for t in run(mylist):
print(t)
[5, 4, 3, 2, 1, 1]
[4, 3, 2, 1]
[3, 2, 1]
[2, 1]
[1]
Or gather all lines in a single array using list -
mylist = [5,4,3,2,1,1]
print(list(run(mylist)))
[
[5, 4, 3, 2, 1, 1],
[4, 3, 2, 1],
[3, 2, 1],
[2, 1],
[1]
]
Maybe this is what you want?
def make_all_zero_and_print(numbers):
while numbers[0] > 0:
print(numbers)
for i in range(len(numbers)):
if numbers[i] > 0:
numbers[i] -= 1
print(numbers)
make_all_zero_and_print([5, 4, 3, 2, 1, 1])
Output:
[5, 4, 3, 2, 1, 1]
[4, 3, 2, 1, 0, 0]
[3, 2, 1, 0, 0, 0]
[2, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]

I have problem with removing last item from list [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 1 year ago.
nums = [0,1,2,2,3,0,4,2]
val = 2
for i in nums:
if i == val:
nums.remove(i)
else:
continue
print(nums)
Result is [0,1,3,0,4,2] instead of [0,1,3,0,4]
Well maybe I am a little bit confused because in the title you ask for removing just the last item but in the question you ask for an expected result. I just took your code and make it work to get the expected output with a list comprehension. It looks like this:
nums_new = [i for i in nums if i != val]
You can ofcourse name nums_new to only nums.
Your mistake becomes clear if you print your data inside the loop:
nums = [0,1,2,2,3,0,4,2]
val = 2
for i in nums:
if i == val:
nums.remove(i)
print(i, nums)
print(nums)
Output:
0 [0, 1, 2, 2, 3, 0, 4, 2]
1 [0, 1, 2, 2, 3, 0, 4, 2]
2 [0, 1, 2, 3, 0, 4, 2]
3 [0, 1, 2, 3, 0, 4, 2]
0 [0, 1, 2, 3, 0, 4, 2]
4 [0, 1, 2, 3, 0, 4, 2]
2 [0, 1, 3, 0, 4, 2]
[0, 1, 3, 0, 4, 2]
Note:
i goes through 0, 1, 2, 3, ..., i.e., not two 2s in a row. That's because you remove the first 2, but "the loop" doesn't care, it still goes to the next position in the list, which then holds the value 3.
You do find the 2 at the end, but since remove removes the first occurrence, it removes the earlier 2.
You have a few options:
Filter
your_list = [1, 2, 3, 4, 2, 3, 4, 2]
filtered_values = filter(lambda value: value != 2, your_list)
The first argument is the filtering function, the second is your values - whatever evaluates to False is removed from the list.
List comprehension
your_list = [1, 2, 3, 4, 2, 3, 4, 2]
filtered_values = [value for value in your_list if value != 2]
There are many other ways of doing it, although those are the most common ways of doing it.
You can also do this with the NumPy module:
import numpy as np
# generate 20 random integers between 0 (inclusive) and 5 (exclusive)
myarr = np.random.randint(0, 5, 20)
print(myarr)
[0 2 0 1 2 0 3 0 0 0 3 4 1 3 1 4 1 0 4 4]
val = 2
myarr = np.delete(myarr, np.where(myarr == val))
print(myarr)
[0 0 1 0 3 0 0 0 3 4 1 3 1 4 1 0 4 4]
myarr = np.delete(myarr, np.where(myarr == val))
In that line we do the following: from the array myarr, delete the elements whenever that element equals val.
The same can be achieved with your initial list, by first converting it to a numpy array:
nums = np.array(nums)

Move Zeroes to the end of the string

I was just doing some leetcode
but this blew my mind.
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
nums = [0, 1, 0, 3 ,12]
k = 0
i=0
while i < len(nums):
print(i)
if nums[i] == 0:
print('inside if=',i)
print('before',nums)
k += 1
print('removed',nums[i])
nums.remove(i)
print('after',nums)
else:
i += 1
print('no change',nums)
print('final',nums)
for j in range (k):
nums.append(0)
print(nums)
and the output is:
0
inside if= 0
before [0, 1, 0, 3, 12]
element to be removed 0
after [1, 0, 3, 12]
0
no change [1, 0, 3, 12]
->1
->inside if= 1
->before [1, 0, 3, 12]
->element to be removed 0
->after [0, 3, 12]
1
no change [0, 3, 12]
2
no change [0, 3, 12]
final [0, 3, 12]
[0, 3, 12, 0, 0]
How can it remove element 1 if it can read that it has to remove 0?
So I got to know my dumb mistake.
Actually remove() is used to remove the element that is mentioned.
Like if I type remove(6)from a list a = [1,2,3,4,5,6]. it removes element 6, not the element that is at 6th position.
so use pop() to do so.

how to find the count the difference back to the previous zero in a list?

I have below list
[7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
and the result list is
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
the result obtained by with the below logic
For each value, count the difference back to the previous zero (or the start of the Series,
whichever is closer).
am trying to implement , but not able to get .
So how to find the previous zero position , such that we can get that series ?
I tried below , but somehow it is failing , and it is seems not good solution
import pandas as pd
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
#print(df)
df_series = df['X']
print(df_series.iloc[-1])
target_series = pd.Series([])
#print(target_series)
def calculate_value(i,actual_index):
if(df_series.iloc[i-1] == 0):
if(i < 0):
zero_position = i + df_series.size-1
if(actual_index - 0 < zero_position):
target_series[actual_index]=actual_index+1
return
else:
target_series[actual_index]=zero_position
return
else:
target_series[actual_index]=target_series[actual_index]+1
return
else:
if(i+df_series.size != actual_index):
calculate_value(i-1,actual_index)
for i in df.index:
if(df_series[i]==0 and i!=0):
target_series[i]=0
elif(df_series[i]!=0 and i==0):
target_series[i]=1
else:
calculate_value(i,i)
print(target_series)
If you want a Pandas one-liner solution:
import pandas as pd
s = pd.Series([7, 2, 0, 3, 4, 2, 5, 0, 3, 4])
(s.groupby(s.eq(0).cumsum().mask(s.eq(0))).cumcount() + 1).mask(s.eq(0), 0).tolist()
Output:
[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
If you stick to the list you can get your result quite easily:
l = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
i = 0
r = []
for element in l:
if element != 0:
i += 1
else:
i = 0
r.append(i)
r
#[1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Here is a working solution for you:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
b = []
z_pos = -1
for i, n in enumerate(a):
if n == 0:
z_pos = i
b.append(i - z_pos)
print(b) # [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
It does not use anything too fancy so I explaining its internal workings is unnecessary I think. If however there is something that is not clear to you let me know.
If you want to use python only, here is the solution:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
z = None
b = []
for i in range(len(a)):
if a[i] != 0 and z== None:
b.append(i+1)
elif a[i] == 0:
b.append(0)
z = 0
else:
z += 1
b.append(z)
b is the required list.
Here is how to do it with a standard list, not Pandas dataframe, but the logic is the same
arr = [7,2,0,3,4,5,1,0,2]
arr2 = []
counter = 1
for item in arr:
if(item==0):
counter = 0
arr2.append(counter)
counter+=1
print(arr2)
You can see the code working here.
Some explanations:
What you want is a sort of counter between two 0 in your array.
So you loop over your array, and each time you encounter a 0 you reset your counter, and you insert the value of your counter each iteration of the loop.
If you are a fan of shortness instead of readability or effectiveness, you can also roll with this:
a = [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]
distances = [([0]+a)[:idx][::-1].index(0) for idx in range(1, len(a)+2)][1:]
Which gives the desired result:
print(distances)
>> [1, 2, 0, 1, 2, 3, 4, 0, 1, 2]
Solution with no for loops or apply, just some pandas groupby fun.
We use
df = pd.DataFrame({'X': [7, 2, 0, 3, 4, 2, 5, 0, 3, 4]})
# make a new column with zeros at zeros and nans elsewhere
df = df.assign(idx_from_0=df.loc[df.X==0])
nul = df['idx_from_0'].isnull()
df.assign(idx_from_0=nul.groupby((nul.diff() == 1).cumsum()).cumsum())
Out[1]:
X idx_from_0
0 7 1.0
1 2 2.0
2 0 0.0
3 3 1.0
4 4 2.0
5 2 3.0
6 5 4.0
7 0 0.0
8 3 1.0
9 4 2.0
The cumsum forward fill add one was taken from this answer.

Categories

Resources