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)
Related
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 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.
I want to solve this question using dict in python.However i am not able to create code out of the logic.
question says Given an array A[] of integers, sort the array according to frequency of elements. That is elements that have higher frequency come first. If frequencies of two elements are same, then smaller number comes first.
Input:
2
5
5 5 4 6 4
5
9 9 9 2 5
Output:
4 4 5 5 6
9 9 9 2 5
t=int(input())
for i in range(t):
n=int(input())
arr=list(map(int,input().split()))
d={}
for i in arr:
d[i]=d.get(0,i)+1
a=max(d[i])
print(i*d[i])
a=a+1
Little bit of code that I tried is as above
import collections
sample = [1, 9, 1, 1, 10, 10, 7, 1, 2, 2, 2, 0, 2, 3, 3, 4, 0, 5]
counter = collections.Counter(sample)
def helper_function(item):
return counter[item], item # returns a tuple
sorted_list = sorted(sample, key=helper_function)
# or if you prefer using lambda
sorted_list = sorted(sample, key=lambda item: (counter[item], item))
print(sorted_list)
Output:
[4, 5, 7, 9, 0, 0, 3, 3, 10, 10, 1, 1, 1, 1, 2, 2, 2, 2]
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.
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]