This question already has answers here:
Removing elements that have consecutive duplicates
(9 answers)
Remove adjacent duplicate elements from a list [duplicate]
(17 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
I want to return a list of items from a sequence without any elements with the same value next to each other and preserving the original item order.
I've written a solution that works but my attempt to make this solution more pythonic does not work. It seems the if statement isn't working; it just returns the whole original sequence in a list.
The solution should be a function and I don't want to use imports.
Def order(iterable):
iter_list = list(iterable)
item_list = []
item_list.append(iter_list[item] for item in range(0, len(iter_list)) if iter_list[item] != iter_list[item -1])
return iter_list
I just need to know why (if iter_list[item] != iter_list[item -1) is not working
Your original code works just fine if you just take what's inside append if we somehow account for the first element. One way is:
out = [iter_list[item] for item in range(0, len(iter_list)) if (item==0 or iter_list[item] != iter_list[item -1])]
If you zip the list with the same list starting at index 1 you're quite close to your goal but you might miss the last element.
data = [0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8]
result = [x for x, y in zip(data, data[1:]) if x != y]
print(result)
This gives you [0, 1, 2, 3, 4, 5, 6, 7], but we would expect an additional 8 in the list.
To get the last value too we can use itertools.zip_longest.
from itertools import zip_longest
data = [0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8]
result = [x for x, y in zip_longest(data, data[1:]) if x != y]
print(result)
This results in [0, 1, 2, 3, 4, 5, 6, 7, 8].
If you don't want to duplicate the list then use islice.
from itertools import islice, zip_longest
data = [0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8]
result = [x for x, y in zip_longest(data, islice(data, 1, None)) if x != y]
print(result)
Related
in this code I'm trying to delete every repeated element in the list and just make all of the elements unique and not repeated, so when I run this code give me an error:
myList = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
repeat = 0
for i in range(len(myList)-1):
for j in range(len(myList)-1):
if myList[i]== myList[j]:
repeat+=1
if repeat>1:
del myList[j]
print("The list with unique elements only:")
print(myList)
the error which apppears is :
Traceback (most recent call last):
File "main.py", line 8, in <module>
if myList[i]== myList[j]:
IndexError: list index out of range
why is that happens and how can I solve it?
It is a really bad idea to modify an array while looping on it as you have no control on the way things are handled.
May I suggest these two solutions to your problem.
The first one is using set.
myList = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
myList = list(set(myList))
print("The list with unique elements only:")
print(myList)
The other solution is using an other array
myList = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
uniques = []
for number in myList:
if number not in uniques:
uniques.append(number)
print("The list with unique elements only:")
print(uniques)
You can convert list to set, it will automatically delete all of repeated elements
a = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
unique_list = list(set(a))
print(a)
Note: We again convert set to list
What is heppening here is that you are deleting some elements in your list, making it shorter.
Since your for loops are running for the lenght of your original list, you will eventuall try to access an index that no longer exists. This will cause you to get "list index out of range"
To see this for your self, you can add a print statement, like so:
myList = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
repeat = 0
for i in range(len(myList)-1):
for j in range(len(myList)-1):
print(i,j,len(myList))
if myList[i]== myList[j]:
repeat+=1
if repeat>1:
del myList[j]
Set data type in Python is used to remove duplicity. Whenever any iterator needs to be viewed with only the unique values in it, it can be converted into a set and that will remove all the duplicate values. For example:
lis=[2,2,3,4]
l=set(lis)
print(l)
Output:
{2, 3, 4}
It can be converted back into the list:
lis=[2,2,3,4]
l=set(lis)
print(l)
l=list(l)
print(l)
Output:
{2, 3, 4}
[2, 3, 4]
Similarly:
myList = [1, 2, 4, 4, 1, 4, 2, 6, 2, 9]
s=set(myList)
l=list(s)
print(l)
Output:
[1, 2, 4, 6, 9]
Frozen sets can also be used for this purpose. Although; elements of the frozen set remain the same after creation i.e, they can't be modified unlike the elements of the set which are mutable(can be modified).
Hope this was helpful!
This question already has an answer here:
Create index list for np.split from the list that already has number for each section
(1 answer)
Closed 3 years ago.
Let's say I've got an array [0, 1, 2, 3, 4, 5, 6, 7] and a tuple: (3, 3, 2).
I'm looking for a way to split my array to 3 array based on my tuple data:
[0, 1, 2]
[3, 4, 5]
[6, 7]
I can write a simple code like this to get what I want, however I'm looking for a correct and pythonic way to do this:
I used lists for simplicity.
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = []
for j in range(i):
lst.append(a[pointer])
pointer += 1
print(lst)
Or this one:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = a[pointer:pointer+i]
pointer += i
print(lst)
Results:
[0, 1, 2]
[3, 4, 5]
[6, 7]
you can use the split method of numpy
import numpy as np
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
c = np.split(a, np.cumsum(b)[:-1])
for r in c:
print(r)
np.split(a, b) splits a by the indices in b along a given axis(0 by default).
If you don't want to modify your input list, you can use an iterator and the itertools module.
>>> from itertools import islice
>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> b = (3, 3, 2)
>>> i = iter(a)
>>> [list(islice(i, x)) for x in b]
[[0, 1, 2], [3, 4, 5], [6, 7]]
In the first step you create an iterator, which starts at the first element of a. Then you iterate in a list comprehension over your numbers in b and in each step you pull accordingly many elements from the iterator and store them in your result list.
One simpler way is this:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
for ind in b:
print(a[:ind])
a = a[ind:]
It loops through slice sizes in b while shortening the original array every time. You can easily append the resulting slices as sublists if you need them for something else. It's almost like one of your solutions except it doesn't use any extra variables and iterates directly through elements of b.
Also, I wouldn't call variables a and b - surely not in this case where variables have clear meanings that you can express through their names. More meaningful names lessen bugs number and make code more clear, becomes a real difference with larger/more complex code. I'd call a at least in_list and b slices, but with more context this could be better.
The most "concise" syntax would be :
ex_array = [0, 1, 2, 3, 4, 5, 6, 7]
extuple = (3, 3, 2)
result = [ex_array[sum(extuple[:iii]):sum(extuple[:iii])+extuple[iii]] for iii in range(len(extuple))]
result would be a list of the expected sub-lists
Re-using the pairwise function from Compare two adjacent elements in same list, you could also:
from itertools import accumulate
from more_itertools import pairwise
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
[a[slice(*s)] for s in pairwise(accumulate((0,)+b))]
That begin said, the np.split answer is probably faster (and easier to read).
This question already has answers here:
How to delete an element from a list while iterating over it in Python? [duplicate]
(2 answers)
Closed 5 years ago.
I want to know how to append all the items that weren't removed into a new list.
challenge = [1, 0, 9, 8, 5, 4, 1, 9, 3, 2, 3, 5, 6, 9]
def remove_values(thelist, value):
newlist = []
while value in thelist:
thelist.remove(value)
newlist.append()
bye = remove_values(challenge, max(challenge))
For example, if I remove all the 9s (the max), how do I append the rest into a new list?
challenge = [1, 0, 9, 8, 5, 4, 1, 9, 3, 2, 3, 5, 6, 9]
# This will append every item to a new List where the value not is max
# You won't need 2 lists to achieve what you want, it can be done with a simple list comprehension
removed_list = [x for x in challenge if x != max(challenge)]
print(removed_list)
# will print [1, 0, 8, 5, 4, 1, 3, 2, 3, 5, 6]
Have a list arr = [1,3,4,5,2,3,4,2,5,7,3,8,1,9,6,2,1,2,1,3,4,3,4,6,9]
want to remove the duplicate values so that the original list should contains single instances of all elements. Do not want to create a extra list and append the elements from list. Also do not want to use inbuilt "set".
Tried to do that with some code as below:
l = len(arr)
for x in range(l):
for y in range(x+1,l):
if arr[x] == arr[y]:
del arr[y]
Tried the above code and its throwing error
"IndexError: list index out of range"
What I understand is whiling deleting the value the size of the list is changing for which its throwing the error. So I made the below changes. But still its failing with same error:
l = len(arr)
for x in range(l):
for y in range(x+1,l):
if arr[x] == arr[y]:
t = y
del arr[y]
y = t - 1
Can some one help me out on this?
Thanks in Advance.
You are trying to make the code more efficient by caching the length of the list in the local variable l. However, that is not helpful because the list is being trimmed inside the loop, and you are not keeping the cached length variable in sync.
for index in range(len(arr)-1,0,-1):
if arr[index] in arr[:index]:
del arr[index]
By going backwards through the array and looking for earlier occurrences of each element, you can avoid having to worry about the length of the list changing all the time.
This method also preserves the order in which elements occur in the original array. Note the instruction is to only remove duplicates (a.k.a. subsequent occurrences).
For example the list [9,3,4,3,5] should reduce to [9,3,4, 5] as the second occurrence of 3 is considered a duplicate and should be removed.
How about this approach:
>>> set(arr)
set([1, 2, 3, 4, 5, 6, 7, 8, 9]) #Just to compare it with the results below.
>>> arr = [1,3,4,5,2,3,4,2,5,7,3,8,1,9,6,2,1,2,1,3,4,3,4,6,9]
>>> arr.sort()
>>> arr
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 9]
>>> for i in arr:
while arr.count(i) > 1:
del arr[i]
>>> arr
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Another approach is to find, after sorting your list, the length of the sublist to delete for each number:
>>> arr = [1,3,4,5,2,3,4,2,5,7,3,8,1,9,6,2,1,2,1,3,4,3,4,6,9]
>>> arr.sort()
>>> arr
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 9]
>>> for i,j in enumerate(arr):
del arr[i+1:i+arr.count(j)]
>>> arr
[1, 2, 3, 4, 5, 6, 7, 8, 9]
If I am given a list of numbers and I want to swap one of them with the next two numbers.
Is there a way to do this in one shot, without swapping the first number twice?
To be more specific, let's say I have the following swap function:
def swap_number(list, index):
'''Swap a number at the given index with the number that follows it.
Precondition: the position of the number being asked to swap cannot be the last
or the second last'''
if index != ((len(list) - 2) and (len(list) - 1)):
temp = list[index]
list[index] = list[index+1]
list[index+1] = temp
Now, how do I use this function to swap a number with the next two numbers, without calling swap on the number twice.
For example: I have the following list: list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Now, how do I swap 3 with the 4 and 5 in one shot?
The expected output would be
list = [0, 1, 2, 4, 5, 3, 6, 7, 8, 9]
Something like this?
def swap(lis, ind):
lis.insert(ind+2, lis.pop(ind)) #in-place operation, returns `None`
return lis
>>> lis = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> lis = swap(lis, 3)
>>> lis
[0, 1, 2, 4, 5, 3, 6, 7, 8, 9]