Say I have this list
x = [1,2,3,1,5,1,8]
Is there a way to find every index that 1 is in the list?
Sure. A list comprehension plus enumerate should work:
[i for i, z in enumerate(x) if z == 1]
And the proof:
>>> x = [1, 2, 3, 1, 5, 1, 8]
>>> [i for i, z in enumerate(x) if z == 1]
[0, 3, 5]
The questioner asked for a solution using list.index, so here is one such solution:
def ones(x):
matches = []
pos = 0
while True:
try:
pos = x.index(1, pos)
except ValueError:
break
matches.append(pos)
pos += 1
return matches
It is somewhat more verbose than mgilson's solution, which I would consider to be more idiomatic Python.
Related
so if
mylist = [2,3,4,1,9,4]
it needs to output
[3,4,9]
because 3 is higher than 2, 4 is higher than 3,1 is NOT higher than 4 and like that continues....
You can employ code similar to the pairwise recipe from the itertools recipe section
>>> it = iter(mylist)
>>> next(it, None)
2
>>> [y for x, y in zip(mylist, it) if y > x]
[3, 4, 9]
This is one approach. Using a simple iteration and enumerate
Demo:
mylist = [2,3,4,1,9,4]
res = []
for i, v in enumerate(mylist):
try:
if mylist[i+1] > v:
res.append(mylist[i+1])
except IndexError:
pass
print(res)
Output:
[3, 4, 9]
How about the simple solution? Loop through the array and check the items
i = 0
prevValue=0;
while i < len(mylist ):
if mylist[i] > prevValue:
print(prevValue)
prevValue=mylist[i]
Here's a one-liner:
[i for idx, i in enumerate(mylist) if idx != 0 and i > mylist[idx - 1]]
Output:
[3, 4, 9]
Soo I read all the answers,thanks for sparing your time to answer my question,I really appreciate that.But I found the most suitable answer for me and the code is:
num = [1,2,3,4,5,2,0,3,9]
for i in range(len(num)):
if(num[i]>num[i-1]):
print(num[i], end = " ")
In Python 2.7, I have two lists of integers:
x = [1, 3, 2, 0, 2]
y = [1, 2, 2, 3, 1]
I want to create a third list which indicates whether each element in x and y is identical, to yield:
z = [1, 0, 1, 0, 0]
How can I do this using list comprehension?
My attempt is:
z = [i == j for i,j in ...]
But I don't know how to complete it.
You are looking for zip
z = [i == j for i,j in zip(x,y)]
But you better add int call to get your desired output
>>> z = [int(i == j) for i,j in zip(x,y)]
>>> z
[1, 0, 1, 0, 0]
else you'll get a list like [True, False, True, False, False]
As ajcr mentions in a comment, it is better to use itertools.izip instead of zip if the lists are very long. This is because it returns an iterator instead of a list. This is mentioned in the documentation
Like zip() except that it returns an iterator instead of a list.
demo
>>> from itertools import izip
>>> z = [int(i == j) for i,j in izip(x,y)]
>>> z
[1, 0, 1, 0, 0]
You can change it a little bit and do:
[x[i] == y[i] for i in xrange(len(x))]
If you use Python3 - change xrange to range
While a list comprehension was specified in the question and the answers above are probably better, I thought I'd chime in with a recursive solution:
def compare_lists(a, b, res=[]):
if len(a) == len(b):
if a == []:
return res
else:
if a[0] == b[0]:
res.append(1)
else:
res.append(0)
return compare_lists(a[1:], b[1:])
else:
return "Lists are of different length."
I have two lists (can be more later), and i want to figure out, which values mach at the same position.
This code below returns matched values, but its not returning the position of the match.
a = [5,0]
b = [5,1]
print list(set(a).intersection(set(b)))
>>5
Use zip and enumerate and check for unique values:
lists = [a, b] # add more lists here if need be...
for idx, items in enumerate(zip(*lists)):
unique = set(items)
if len(unique) == 1:
# idx = position, unique.pop() == the value
print idx, unique.pop()
def check_equal(lst):
return lst[1:] == lst[:-1]
def get_position_and_matches(*lists):
shortest_list = min(lists, key=len)
for index,item in enumerate(shortest_list):
matching = [l[index] for l in lists]
if check_equal(matching):
print "Index: {0}, Value: {1}".format(index, shortest_list[index])
one = [1, 3, 4, 6, 2]
two = [1, 3, 4, 2, 9, 9]
three = [2, 3, 4]
get_position_and_matches(one, two, three)
This will show you the position of the match (assuming the value None is not a valid element)
a=[1,2,3]
b=[0,2,3]
c=[3,2,1]
l = [a, b, c] # add any number of lists
z = zip(*l)
pos = 0
for i in z:
if reduce(lambda x, y: x if x == y else None, i):
print pos
pos += 1
or, if you wanted to keep the match for each position:
matches=[reduce(lambda x, y: x if x == y else None, i) for i in z]
would produce
[None, 2, None]
You could write your own method:
a = [1, 2, 3, 4, 5]
b = [5, 4, 3, 2, 1]
c = [3, 3, 3, 3, 3]
allLists = [b, c] # all lists but the first
for i in range(len(a)):
good = True
for l in allLists:
if l[i] != a[i]:
good = False
break
if good:
print(i, a[i])
edited to make it easier to add more lists
matching_indexes = [i for i in range(len(a)) if a[i] == b[i] == c[i]]
Can be used. A simple list comprehension to test each individual value of a,b and c. More or less == can be added for each list to be compared. However, this assumes all the lists are of the same length or that a is the shortest list.
This is the answer to as many lists as you want to use
a = [5,0,1,2]
b = [5,2,3,2]
lists = [a,b,b,a,a]
d = dict()
for l in lists:
for i in range(len(a)):
if i not in d.keys():
d[i] = a[i]
elif d[i] != l[i]:
d[i] = -1
for i in d.keys():
if d[i] != -1:
print d[i], i
This question already has answers here:
Remove all occurrences of a value from a list?
(26 answers)
Closed 9 years ago.
If I have a bit of Python like:
n = [1, 3, 5, 1]
n.remove(1)
print n
n will return [3, 5, 1] because .remove() quits after it finds its first match. What could I do to return just [3, 5], having found all matches (or in this case, all the 1s)?
If creating a new list is fine:
n = [x for x in n if x != 1]
Of course you could also use slice assignment to modify the list in place:
n[:] = [x for x in n if x != 1]
use filter function
n = [1, 3, 5, 1]
filter(lambda a:a is not 1,n)
[3,5]
edit
n = [1, 3, 5, 1]
filter(lambda a:a != 1,n)
[3,5]
Simple List Comprehension -
>>> n = [1, 3, 5, 1]
>>> n = [e for e in n if e != 1]
>>> n
[3, 5]
If you wanted to remove more than one elements -
>>> g = [1,3]
>>> n = [e for e in n if e not in g]
>>> n
[5]
This is not how I'd normally do this, but:
n = [1, 3, 5, 1]
REMOVECHAR = 1
while REMOVECHAR in n:
n.remove(REMOVECHAR)
# could also do:
# while 1:
# try: n.remove(REMOVECHAR)
# except ValueError as e: break
If I were doing it, I would use a list comp to make a new list.
n = [1,3,5,1]
REMOVECHAR = 1
nn = [element for element in n if element != REMOVECHAR]
You could iterate backwards through the list and pop elements that match.
def remove_all_in_place(target, sequence):
cursor = len(target) - 1
while cursor >= 0:
if sequence[cursor] == target:
sequence.pop(cursor)
cursor -= 1
List comprehensions might be faster since they are optimized, but they aren't in-place operations. For native Python implementations, I think this would be fastest, as well as being true in-place.
I know this question has been asked lots of times, but I am not asking how to remove duplicate elements from a list only, I want to remove the duplicated element as well.
For example, if I have a list:
x = [1, 2, 5, 3, 4, 1, 5]
I want the list to be:
x = [2, 3, 4] # removed 1 and 5 since they were repeated
I can't use a set, since that will include 1 and 5.
Should I use a Counter? Is there a better way?
This should be done with a Counter object. It's trivial.
from collections import Counter
x = [k for k, v in Counter([1, 2, 5, 3, 4, 1, 5]).iteritems() if v == 1]
print x
Output:
[2, 3, 4]
Maybe this way:
[_ for _ in x if x.count(_) == 1]
EDIT: This is not the best way in term of time complexity as you can see in the comment above, sorry my mistake.
Something more verbose and O(n):
x = [1, 2, 2, 3, 4]
def counts_fold(acc, x):
acc[x] = acc[x]+1 if x in acc else 1
return acc
counts = reduce(counts_fold, x, {})
y = [i for i in x if counts[i] == 1]
print y
How about
duplicates = set(x)
x = [elem for elem in x if elem not in duplicates]
This has the advantage of being O(n) instead of O(n^2).
Edit. Indeed my bad, I must have been half asleep. Mahmoud's answer above is the correct one.