array = [1, 1, 1, 1, 1, 1, 2]
new_array = [x for x in array if array[array.index(x)] != array[array.index(x) + 1]]
print(new_array)
Hi, I'm trying to write a program that will check if a content of an index (example: list[0]) equals to next index and if not append the number that differs and I tried to use a new skill I learned which is list comprehension and I don't quite understand why doesn't it work how it should work
To make it more clear what I mean is if I am given an array with all numbers the same except one number which in this case is two I want to append it in a list I also added a picture to make it even more clear
You can use this simple one liner
print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
Note: I'm using min() to just to get the element from set.
Output:
>>> a=[1, 1, 2]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
2
>>> a = [17, 17, 3, 17, 17, 17, 17]
>>> print(a[0] if a.count(a[0]) == 1 else min(set(a).difference(a[:1])))
3
IndexError: list index out of range means you are passing an index that isn't present in the list. And that error is raised in this part:
array[array.index(x) + 1]
When x is the last element error is raised. Because there is no index after the last element. In your case, using list comprehension isn't the best choice, you should prefer for loop.
it may help you:
list = [1, 1, 2, 3, 4, 4]
for i, j in enumerate(list[:-1]):
if j == list[i+1]:
#dosomething
Related
What I have right now:
a_list = [25, 23, 12, 8, 4 ,2, 1]
new_list = []
for i, num in enumerate(a_list):
new_num = num - num[i+1]
new_list.append(new_num)
print(new_list)
#Error: new_num = num - num[i+1]
TypeError: 'int' object is not subscriptable
#Expected: [2, 11, 4, 2, 1]
zip is appropriate here, instead of enumerate. Simply zip a_list with a_list[1:] (so that you can "see" two consecutive elements) and find differences.
new_list = [i-j for i, j in zip(a_list, a_list[1:])]
The reason enumerate doesn't work with your implementation is that you want to index an integer in a_list by num[i+1] which is nonsensical.
If you absolutely want to use enumerate, one important thing is to ensure that you don't want get an IndexError, i.e. you don't want to index beyond the list. One way to ensure that doesn't happen is to only enumerate until a_list[:-1]. Then make sure you index a_list (and not num) and you're good to go.
new_list = []
for i, num in enumerate(a_list[:-1]):
new_num = num - a_list[i+1]
new_list.append(new_num)
Output:
[2, 11, 4, 4, 2, 1]
You seem to want:
a_list = [25, 23, 12, 8, 4 ,2, 1]
new_list = [a - b for a, b in zip(a_list, a_list[1:])]
print(new_list)
If you use a library like numpy, this is simpler:
import numpy as np
a_arr = np.array([25, 23, 12, 8, 4 ,2, 1])
new_arr = a_arr[:-1] - a_arr[1:]
print(new_arr)
Both solutions do the same thing using slicing, taking the original list and pairing each element with the same list, minus the first element. zip() automatically omits the last element from the first list, since there is no element to pair it with in the second list. numpy wants you to tell it to omit the last element (a_arr[:-1]) so that they have the same size.
You're trying to use indices with num, which is the value at position i in the list, not the list. Iterate over the list with range(a_list)-1, so that you access the numbers at positions i and i+1 directly from the list.
Okay, it's Pretty Simple...What you can do basically just subtract arr[index] - arr[index + 1] and append it to a new list and after just print it note range should be (0, old_list.len() - 1)
a_list = [25, 23, 12, 8, 4 ,2, 1] #old list
nw_lst = [] #new list to print and where we will append
size = len(a_list); #Size of the old_list
for i in range(0, size-1):
x = a_list[i] - a_list[i + 1] #claculating difference
nw_lst.append(x) #appending the difference to new list
print(nw_lst) #printing new list
OUTPUT:
[2, 11, 4, 4, 2, 1]
I need to seek the "matchingpoint" of two list where List "a" is bigger than List "b".
So far I've found this earlier post:
Check if a list is part of another list while preserving the list sequence
That helps a lot. But I need to now, where the lists fit.
a = [3, 4, 1, 2, 4, 1, 5]
b = [4, 1, 2]
"b" fits in "a" but instead of a TRUE value I would like to have a[1] as first matchingpoint
You could use next to fetch the first matching point:
a = [3, 4, 1, 2, 4, 1, 5]
b = [4, 1, 2]
starting_point = next((a[i] for i in range(len(a)) if b == a[i:i + len(b)]), -1)
print(starting_point)
Output
4
UPDATE
If you need both the index and the value at the index, return the index instead of the value, for example:
position = next((i for i in range(len(a)) if b == a[i:i + len(b)]), -1)
print("position", position)
print("starting point", a[position])
Output
position 1
starting point 4
Note the change, now is i instead of a[i]
Let's say we have this array:
arr2 = [2, 3, 1, 2, 2]
I've tried the following:
for i,x in enumerate(arr2):
if x == 2 and x[i+1] == 2:
print('TwosPair')
But receiving the following error:
TypeError: 'int' object is not subscriptable
Shouldn't I be able to check the previous index / next one, using enumerate?
I also tried the following:
for i,x in enumerate(arr2):
if x == 2 and x[arr2.index(i)+1] == 2:
print('TwosPair')
But getting this error now:
ValueError: 0 is not in list
What 0 is it talking about?
You are a bit unclear, however if you want to check if the previous index has the same value as the next index relative. Zip will allow you iterate over the two lists the frist is the original and the second is sliced to be one element a head since is its frist item is one index ahead the original allowing to access the current and next indexes of the original list
def TwosPair(list_1):
for curr, next in zip(list_1, list_1[1:]):
if curr == 2 and next == 2: print('TwosPair')
arr2 = [2, 3, 3, 1, 2, 2, 9, 4, 4]
for i in range(len(arr2)-1):
if arr2[i] == arr2[i+1]:
print('Same next & current values!')
you can use this to find the current and next values when both of them have the same value.
Does this do what you need it to?
arr2 = [2, 3, 1, 2, 2]
for i,x in enumerate(arr2):
if i < len(arr2)-1 and arr2[i+1] == x:
print('TwosPair')
This accepts any iterable,
including generators and containers such as a list,
and reports on whether two adjacent elements are equal.
from typing import Iterable
def has_adjacent_dup(a: Iterable):
sentinel = object() # might use None if None won't appear in input
prev = sentinel
for i in a:
if prev == i:
return True
prev = i
return False
if has_adjacent_dup(arr2):
print('Pair')
You can use zip():
arr2 = [2, 3, 1, 2, 2]
for x,y in zip(arr2,arr2[1:]):
if x == y == 2:
print('TwosPair')
Output:
TwosPair
To answer your specific question, the 0 it is talking about is the 0 value that i takes in the first iteration of the enumerate generator and then when it tries to find that i in the array via arr2.index(i), it throws an error
I believe your approach is basically sound -- we just need to tweak it a little. First, we're going to use the second argument to enumerate() to make its generated value the next index. Second, we're going to limit the array loop to all but the last item so we don't overflow the array indicies. Finally, we'll use some fun Python syntax to simplify the test:
array = [2, 3, 1, 2, 2]
for next_index, element in enumerate(array[:-1], 1):
if element == 2 == array[next_index]:
print('TwosPair')
One efficient implementation of this requirement in Python is to use itertools.groupby.
from itertools import groupby
for k, g in groupby(arr):
if k == 2:
next(g)
for _ in g:
print("TwosPair")
So, I don't understand why my output returns [1, 1, 3, 1, 3], when what I want, and thought, was [1,1,1].
the_list = [1, 2, 1, 2, 3, 1, 2, 3, 4]
target = 1
def keep(the_list, target):
index = 0
for x in the_list:
if x != target:
del the_list[index]
else:
pass
index += 1
print(the_list)
When you delete an item from a list at a specific index, all the items after the specified index get moved forward by 1 since there can be no gap in a list, so after you delete the 2 at index 1, for example, in the next iteration x would become 2 at the index 2 when it used to be at index 3, so your own index variable would be pointing to the wrong item.
To delete items from a list in-place, you should instead count backwards from the end of the list so that the re-indexing of the list after you delete an item won't affect the accuracy of your index counter:
def keep(the_list, target):
index = len(the_list) - 1
while index >= 0:
if the_list[index] != target:
del the_list[index]
index -= 1
so that:
the_list = [1, 2, 1, 2, 3, 1, 2, 3, 4]
target = 1
keep(the_list, target)
print(the_list)
would output:
[1, 1, 1]
But keep in mind that deleting an item from a list is inherently inefficient since it has an average time complexity of O(n) for having to move items after the given index, so deleting multiple items from a list becomes quadratic in complexity. It's much more efficient to use list comprehension to construct a new list from the old one by retaining only items that are equal to the target value. So even though the code above shows you how to correctly delete items from a list in-place, you should not actually use it in any production code.
It is gonna be much cleaner if you use list comprehension to check your list elements and return only what you need.
the_list = [1, 2, 1, 2, 3, 1, 2, 3, 4]
target = 1
new_list = [i for i in the_list if i == target]
List comprehensions are much more readable because its intent is explicit. A loop maybe used to do a lot of different things like more complex aggregations or more processing tasks. In contrast, a list comprehension is only meant to do one thing which is build a new list.
As I am new to programming in Python. I am trying to remove particular elements from array using for loop which looks like
a=[2,3,1,4,1,1,1,5]
n=a.count(1)
for i in range (len(a)-n):
if (a[i]==1):
del a[i]
else:
a[i]=a[i]
print (a)
I want to remove 1 from array a. But, I am getting result as:
[2, 3, 4, 1, 1, 5].
That is 1 still exists in my new array. Can somebody please answer my problem?
try like this:
a = [2,3,1,4,1,1,1,5]
a = [x for x in a if x!=1] # this is called list comprehension
note Never modify list while iterating
Use a while loop and the remove method:
a = [2, 3, 1, 4, 1, 1, 1, 5]
while 1 in a:
a.remove(1)
print a
The real answer to your question (which none of the other answers addresses) is that every time you remove an item, the index i moves past it.
in your case:
a = [2,3,1,4,1,1,1,5]
after deleting the 5th item in the original list, the pointer moves to the 6th item, and the new 5th item (the second 1 in the sequence of three 1s) is skipped.
Regarding the comment never modify a list in a loop, try to implement an in-place algorithm like Fisher-Yates without modifying the list. Never say never. Know what you're doing.
The OP changes the list in-place, not creating a new list.
There are two methods, the second is safe, the first might be faster.
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(len(a)-1, -1, -1):
if a[i] == toremove:
del a[i]
and
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(a.count(toremove)):
a.remove(toremove)
The second removes the element however many times it exists (before the loop). Since we are not iterating on the list, it is safe to use the remove method.
Both fragments should be O(n) (but haven't done the calculations).
You can copy a and then remove but you cannot iterate over and delete elements from the same list, if your list starts with n elements python will have n pointers to each element so removing elements from the list as your are iterating over it will cause elements to be missed.python has no way of knowing you have removed elements from the list:
a = [2,3,1,4,1,1,1,5]
for ele in a[:]:
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
You can also use reversed which returns and iterator avoiding creating a whole copy of the list at once:
a = [2,3,1,4,1,1,1,5]
for ele in reversed(a):
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
Or using a list comprehension with the [:] syntax so we actually update the original object:
a[:] = (ele for ele in a if ele != 1)
All the above are linear operations using a single pass over a.
Actually as the del statement will remove elements from your list , and as the list that you bound in your loop doesn't been update after the first deleting you remove incorrect elements from your list , so if you want to use del you need to make the list name in your loop to reference to new list , that you can use a function for this aim , but as a more python way you can just use a list comprehension:
>>> a=[2,3,1,4,1,1,1,5]
>>> a=[i for i in a if i !=1]
>>> a
[2, 3, 4, 5]
Or you can use filter :
>>> a=[2,3,1,4,1,1,1,5]
>>> a=filter(lambda x: x !=1,a)
>>> a
[2, 3, 4, 5]