If you don't have any other indexes or sorted information for your objects, then you will have to iterate until such an object is found:
next(obj for obj in objs if obj.val == 5)
This is however faster than a complete list comprehension. Compare these two:
[i for i in xrange(100000) if i == 1000][0]
next(i for i in xrange(100000) if i == 1000)
The first one needs 5.75ms, the second one 58.3ยตs (100 times faster because the loop 100 times shorter).
Answer from eumiro on Stack OverflowIf you don't have any other indexes or sorted information for your objects, then you will have to iterate until such an object is found:
next(obj for obj in objs if obj.val == 5)
This is however faster than a complete list comprehension. Compare these two:
[i for i in xrange(100000) if i == 1000][0]
next(i for i in xrange(100000) if i == 1000)
The first one needs 5.75ms, the second one 58.3ยตs (100 times faster because the loop 100 times shorter).
This will return the object if found, else it will return "not found"
a = [100, 200, 300, 400, 500]
def search(b):
try:
k = a.index(b)
return a[k]
except ValueError:
return 'not found'
print(search(500))
python - Search over a list and return the index at first occurrence then assign - 1 if value not there - Stack Overflow
python - Find index of first occurrence in sorted list - Stack Overflow
Python to search a string for the first occurrence of any item in a list - Stack Overflow
First occurrence of a number in python list - Stack Overflow
Videos
Your logic is wrong, you have a so called sorted list of strings which unless you compared as integer would not be sorted correctly, you should use integers from the get-go and bisect_left to find index:
from bisect import bisect_left
sortedlist = sorted(map(int, ['0', '0', '0', '1', '1', '1', '2', '2', '3']))
count = 0
def get_val(lst, cn):
if lst[-1] < cn:
return "whatever"
return bisect_left(lst, cn, hi=len(lst) - 1)
If the value falls between two as per your requirement, you will get the first index of the higher value, if you get an exact match you will get that index:
In [13]: lst = [0,0,2,2]
In [14]: get_val(lst, 1)
Out[14]: 2
In [15]: lst = [0,0,1,1,2,2,2,3]
In [16]: get_val(lst, 2)
Out[16]: 4
In [17]: get_val(lst, 9)
Out[17]: 'whatever'
As there are some over-complicated solutions here it's worth posting how straightforwardly this can be done:
def get_index(a, L):
for i, b in enumerate(L):
if b >= a:
return i
return "over"
get_index('1', ['0','0','2','2','3'])
>>> 2
get_index('1', ['0','0','0','1','2','3'])
>>> 3
get_index('4', ['0','0','0','1','2','3'])
>>> 'over'
But, use bisect.
I think this would do what you want:
months = ["January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"]
indices = [s.find(month) for month in months]
first = min(index for index in indices if index > -1)
First, we get the first appearance of each month (or -1 if not present), then we get the minimum of the indices, except where it's -1. This will throw a ValueError if none are found, which may or may not be what you want.
As Two-Bit Alchemist has commented, you could short-cut for efficiency:
months = ["January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"]
first = None
for month in sorted(months, key=len):
i = s[:first].find(month) # only search first part of string
if i != -1:
if i < first or first is None:
first = i
if i < len(month): # not enough room for any remaining months
break
I would use re for conceptual simplicity. It's also easy to extend the code to do something more complex if you need to later.
import re
mytext = open('text.txt','r')
mytext = mytext.read()
months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
months_match = re.search("|".join(months), mytext)
print match_obj.start()
http://docs.python.org/2/library/re.html
Use index to find the first occurrence of an item in a list
>>> l = [0,0,0,0,0,1,1,1,1,1,1,1]
>>> l.index(0)
0
>>> l.index(1)
5
A solution that works for more than just 0 and 1 can be based to a set containing the elements we encountered so far:
l = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
s = set()
for x in l:
if x not in s:
print("first occurrence of %s" % x)
s.add(x)
print(x)
Result:
first occurrence of 0
0
0
0
0
0
first occurrence of 1
1
1
1
1
1
1
1
Sequences have a method index(value) which returns index of first occurrence - in your case this would be verts.index(value).
You can run it on verts[::-1] to find out the last index. Here, this would be len(verts) - 1 - verts[::-1].index(value)
Perhaps the two most efficient ways to find the last index:
def rindex(lst, value):
lst.reverse()
i = lst.index(value)
lst.reverse()
return len(lst) - i - 1
import operator
def rindex(lst, value):
return len(lst) - operator.indexOf(reversed(lst), value) - 1
Both take only O(1) extra space and the two in-place reversals of the first solution are much faster than creating a reverse copy. Let's compare it with the other solutions posted previously:
def rindex(lst, value):
return len(lst) - lst[::-1].index(value) - 1
def rindex(lst, value):
return len(lst) - next(i for i, val in enumerate(reversed(lst)) if val == value) - 1
Benchmark results, my solutions are the red and green ones:

This is for searching a number in a list of a million numbers. The x-axis is for the location of the searched element: 0% means it's at the start of the list, 100% means it's at the end of the list. All solutions are fastest at location 100%, with the two reversed solutions taking pretty much no time for that, the double-reverse solution taking a little time, and the reverse-copy taking a lot of time.
A closer look at the right end:

At location 100%, the reverse-copy solution and the double-reverse solution spend all their time on the reversals (index() is instant), so we see that the two in-place reversals are about seven times as fast as creating the reverse copy.
The above was with lst = list(range(1_000_000, 2_000_001)), which pretty much creates the int objects sequentially in memory, which is extremely cache-friendly. Let's do it again after shuffling the list with random.shuffle(lst) (probably less realistic, but interesting):


All got a lot slower, as expected. The reverse-copy solution suffers the most, at 100% it now takes about 32 times (!) as long as the double-reverse solution. And the enumerate-solution is now second-fastest only after location 98%.
Overall I like the operator.indexOf solution best, as it's the fastest one for the last half or quarter of all locations, which are perhaps the more interesting locations if you're actually doing rindex for something. And it's only a bit slower than the double-reverse solution in earlier locations.
All benchmarks done with CPython 3.9.0 64-bit on Windows 10 Pro 1903 64-bit.
Use a set to check if you had processed that item already:
visited = set()
L = ['a','a','a','b','b','b','b','b','e','e','e'.......]
for e in L:
if e not in visited:
visited.add(e)
# process first time tasks
else:
# process not first time tasks
You can use unique_everseen from itertools recipes.
This function returns a generator which yield only the first occurence of an element.
Code
from itertools import filterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
Example
lst = ['a', 'a', 'b', 'c', 'b']
for x in unique_everseen(lst):
print(x) # Do something with the element
Output
a
b
c
The function unique_everseen also allows to pass a key for comparison of elements. This is useful in many cases, by example if you also need to know the position of each first occurence.
Example
lst = ['a', 'a', 'b', 'c', 'b']
for i, x in unique_everseen(enumerate(lst), key=lambda x: x[1]):
print(i, x)
Output
0 a
2 b
3 c
Hello everyone, I'm currently working with graphs on python and I'm trying to implement a program for school where I can find all the roads to certain nodes and print the node found first. I'm stuck on this last part specifically. After doing my function I finally get my roadmap as such:
([[5], [4, 5], [4], [3, 4], [3], [1, 3], [1], [3, 7], [7], [1, 7], [1, 8], [8], [2, 7], [2], [2, 6], [6]],)
Where I was looking for the roads starting from 5 to 6,7 and 8. As you can see here I found [7] first.
My question is : how do I print only the first value found out of a list of 3 or more numbers? In this case in particular it would be 7 (notice I only want the instance where 7 is alone, not [3,7] or [1,7]
I already tried:
item for item in tuple if item==7 or item==8 or item==9
to no avail
Thank you!