why 2 and 4 remain in the 2 example? [duplicate] - python

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 years ago.
I need to remove all unique objects in the given lists.
My code passes 1,3,4 checks but doesn't pass 2nd one, it returns [2,4], why not []?
def checkio(data):
for i in data:
if data.count(i) == 1 :
data.remove(i)
return data
if __name__ == "__main__":
assert isinstance(checkio([1]), list), "The result must be a list"
assert checkio([1, 2, 3, 1, 3]) == [1, 3, 1, 3], "1st example"
assert checkio([1, 2, 3, 4, 5]) == [], "2nd example"
assert checkio([5, 5, 5, 5, 5]) == [5, 5, 5, 5, 5], "3rd example"
assert checkio([10, 9, 10, 10, 9, 8]) == [10, 9, 10, 10, 9], "4th example"

The problem here is that you are removing elements from a list while iterating through it, which you should never do.
The iteration for i in data keeps moving the index it's looking at forward. So, when you remove the first element in the list, the next item is moved to index 0 and the loop moves on to look at the element at index 1, skipping over the item that was moved to index 0.
Instead, you can build up a new list containing items that meet your criteria:
items = []
for i in data:
if (data.count(i) > 1):
items.append(i)
return items
Or do something like this:
return [i for i in l1 if l1.count(i) > 1]

The 'remove' function automatically recreates the list. So when "1" was removed, "2" was put in that slot, so it won't check that same position again, which is why alternating items are remaining. However, you can still implement the same function as you have, but instead work from the back of the list and iterate to the front:
def checkio(data):
for i in range(len(data)-1,-1,-1):
if data.count(data[i]) == 1 :
data.remove(data[i])
return data

Related

Python not iterating over array with for loop [duplicate]

This question already has answers here:
Python invert every two elements of list
(5 answers)
Closed 3 months ago.
Write a program that fills an array of 10 elements with random numbers from 1 to 10, and then swaps the first element with the second, the third with the fourth, and so on. Display the original and transformed array
Here is my solution, but Python doesn't want to sort the array and it stays the same:
from random import randint
numbers = []
for i in range(10):
numbers.append(randint(1, 10))
print(numbers)
a = 0
for a in range(10):
numbers[-1], numbers[i] = numbers[i], numbers[-1]
a = a + 2
print(numbers)
I have tried replacing elements with a loop by numbers[a] = numbers[a+1] , But I kept getting the error:
IndexError: list index out of range
There's a couple things here:
1: as #bereal said, range() has a tird optional step argument, and I've never seen a better time to use it. Check out the documentation for range() https://docs.python.org/3/library/functions.html#func-range
2: I see you reference numbers[-1] even though I think you mean number[-i], it will still reference numbers[-1] on the first iteration, thereby giving an error.
You can make the swap when its not an even number like this:
for a in range(10):
if a % 2 == 1:
tempNumber = numbers[a]
numbers[a] = numbers[a-1]
numbers[a-1] = tempNumber
And then you will have
First output:
[9, 7, 4, 7, 4, 3, 1, 9, 9, 9]
Final output:
[7, 9, 7, 4, 3, 4, 9, 1, 9, 9]

How to remove some elements from a list and append them at the beginning of the list in Python

Suppose that I have a list that has [0, 1, 2, 3 , 4, 5, 6] in it. I want to remove those elements that are greater than or equal to 3 and add those removed elements to the beginning of the list. So I wrote the code below:
list = [0, 1, 2, 3, 4, 5, 6]
new_list =[]
for number in list:
if number >= 3:
dropped_number = list.pop()
new_list.append(dropped_number)
new_list.sort()
new_list += list
print(new_list)
However, when I ran the code, the result was displayed as [5, 6, 0, 1, 2, 3 , 4]. Could anyone please explain to me at which step I did wrong here?
There are two issues with your code.
the number you obtain with list.pop() is not the one you just checked with your condition (it is merely the last one in the list)
When you reach 3, list.pop() removes 6,
When you reach 4, list.pop() removes 5,
You never reach 5 because you're at the end of what remains of the list at that point.
removing items from a list within a for-loop on the same list will cause the for-loop to skip items or complain that the list changed during iterations. So, even if you were to pop the appropriate number, your loop would miss items.
You also don't need to sort new_list every time you add to it, you can do it once at the end, but that just optimization.
Instead of a for-loop, you could use the sort method with a key parameter that returns a boolean indicating True for elements that do not meet your conditions (i.e that will be shifted to the right). Because Python's sort is stable, this will only place elements in two groups without otherwise changing their relative order.
L = [0, 2, 4, 6, 1, 3, 5]
L.sort(key=lambda x: not x>=3)
print(L) # [4, 6, 3, 5, 0, 2, 1]
If you need a more procedural solution, you can separate the values in two lists that you stick together at the end:
L = [0, 2, 4, 6, 1, 3, 5]
left,right = [], []
for x in L:
if x >= 3: left.append(x)
else: right.append(x)
L = left + right
# [4, 6, 3, 5, 0, 2, 1]
Modifying a list while iterating over it is usually problematic. What if instead you thought of the problem as building a new list out of two subsets of the original list?
>>> old_list = list(range(7))
>>> [i for i in old_list if i >= 3] + [i for i in old_list if i < 3]
[3, 4, 5, 6, 0, 1, 2]
The reason your program doesn't work is because you are modifying the list whilst searching through it. Instead, you can start by adding the elements >= 3 to a new list and then separately appending the elements < 3 to the list. Also, considering you are created a second 'new_list', there is no need to remove the elements from the first list.
Your new code:
list = [0, 1, 2, 3, 4, 5, 6]
new_list = []
# Append numbers greater than 3 to the new list
for number in list:
if number >= 3:
new_list.append(number)
# Append the numbers less than 3 to the new list
new_list += list[0:list.index(new_list[0])]
print(new_list)
Just to note, this method takes a section of the original list from position 0, to the position (.index) of the first item in the new list, which automatically generates the < 3 condition as the first item in the new list corresponds to the items before the >= 3 condition is met.
list[0:list.index(new_list[0])]

I don't understand the difference between these codes [duplicate]

This question already has answers here:
Difference between del, remove, and pop on lists
(14 answers)
Closed 2 years ago.
data = [2, 4, 3, 1, 5, 10, 9]
data.pop()
print(data)
result: [2, 4, 3, 1, 5, 10]
the above is what i think makes sense
however,
data = [2, 4, 3, 1, 5, 10, 9]
Print(data.pop())
I got this
Result : 9
what is the difference?
In the 1st situation, you are printing a list of data. I have re-lined the code and added comments to make it more understandable:
Scenario 1:
data = [2, 4, 3, 1, 5, 10, 9] # the given data list
data.pop() # pop the last element off the list
print(data) # print 'data' (which is the list)
The reason why the result here is [2, 4, 3, 1, 5, 10] is because you are popping from the list, and then printing the list itself.
Scenario 2:
data = [2, 4, 3, 1, 5, 10, 9] # the given data list
print(data.pop()) # print the value returned by data.pop(), which is 9
# Result : 9
List.pop() is a method that returns the popped value from the list. So, by doing print(data.pop()), you are requesting to print the single popped value rather than the data list in its entirety.
See the Python documentation on the List.pop() method here.
The pop() method returns the value which was deleted from the list.
If you try to print that d.pop() it just returns the removed value.
When you use pop( ) it returns the last element of the list and internally it deletes last element from the list.
Note that in the first code you’re printing data ( the list ) and in the second one you’re printing what pop returns

Group Consecutive Increasing Numbers in List [duplicate]

This question already has answers here:
Decompose a list of integers into lists of increasing sequences
(6 answers)
Closed 2 years ago.
How can I group together consecutive increasing integers in a list? For example, I have the following list of integers:
numbers = [0, 5, 8, 3, 4, 6, 1]
I would like to group elements together as follow:
[[0, 5, 8], [3, 4, 6], [1]]
While the next integer is more than previous, keep adding to the same nested list; ones the next integer is smaller, add nested list to main list and start again.
I have tried few different ways (while loop, for loop, enumerate and range), but cannot figure out how to make it append to the same nested list as long as next integer is larger.
result = []
while (len(numbers) - 1) != 0:
group = []
first = numbers.pop(0)
second = numbers[0]
while first < second:
group.append(first)
if first > second:
result.append(group)
break
You could use a for loop:
numbers = [0, 5, 8, 3, 4, 6, 1]
result = [[]]
last_num = numbers[0] # last number (to check if the next number is greater or equal)
for number in numbers:
if number < last_num:
result.append([]) # add a new consecutive list
result[-1].append(number)
last_num = number # set last_num to this number, so it can be used later
print(result)
NOTE: This doesn't use .pop(), so the numbers list stays intact. Also, one loop = O(N) time complexity!!
If pandas are allowed, I would do this:
import pandas as pd
numbers = [0, 5, 8, 3, 4, 6, 1]
df = pd.DataFrame({'n':numbers})
[ g['n'].values.tolist() for _,g in df.groupby((df['n'].diff()<0).cumsum())]
produces
[[0, 5, 8], [3, 4, 6], [1]]
You can do this:
numbers = [0, 5, 8, 3, 4, 6, 1]
result = []
while len(numbers) != 0:
secondresult = []
for _ in range(3):
if numbers != []:
toappend = numbers.pop(0)
secondresult.append(toappend)
else:
continue
result.append(secondresult)
print(result)
use while and for loops. and append them to secondresult and result

Printing a singly list like an array, problem is last comma still stays when I don't want it to [duplicate]

This question already has answers here:
Python: How to not print comma in last element in a for loop?
(3 answers)
Closed 2 years ago.
def printList(self):
node=self.head
#check if list is empty (when there is no head element)
if self.head is None:
print("Empty List")
return
#prints list if not empty
print("[",end="")
while node is not None:
print(node.val, end=",")
node = node.next
print("]")
This is what I have so far, and the output I get is
[A,A,B,]
Just wondering if there is a simpler way of just getting rid of the last character
I cant put an answer but I just did it
if node.next is None:
print(node.val, end="")
One way I can think is using a list to store the data and forming a str out of it using join
Example:
#using join
my_list = []
for i in range(10):
my_list.append(i)
my_str = ', '.join(str(j) for j in my_list)
print(my_str)
print(f'[{my_str}]')
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
If you just want to turn a list of string to one string, use join:
",".join(something_iterable)
For example:
>>> this_is_a_list = [ "AA", "BB", "CC" ]
>>> print(",".join(this_is_a_list))
AA,BB,CC

Categories