Python - for with counter [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing the index in Python for loops
I wonder: does Python have something like?
for (i=0; i < length; i += 1){ .... }
Of course, I might say
i = 0
for item in items:
#.....
i += 1
but I think there should be something similar to for(i = 0;...), shouldn't it?

Use the enumerate() function:
for i, item in enumerate(items):
print i, item
or use range():
for i in range(len(items)):
print i
(On python 2 you'd use xrange() instead).
range() let's you step through i in steps other than 1 as well:
>>> list(range(0, 5, 2))
[0, 2, 4]
>>> list(range(4, -1, -1))
[4, 3, 2, 1, 0]
You usually don't need to use an index for sequences though; not with the itertools library or the reversed() function; most usecases for 'special' index value ranges are covered:
>>> menu = ['spam', 'ham', 'eggs', 'bacon', 'sausage', 'onions']
>>> # Reversed sequence
>>> for dish in reversed(menu):
... print(dish)
...
onions
sausage
bacon
eggs
ham
spam
>>> import itertools
>>> # Only every third
>>> for dish in itertools.islice(menu, None, None, 3):
... print(dish)
...
spam
bacon
>>> # In groups of 4
>>> for dish in itertools.izip_longest(*([iter(menu)] * 4)):
... print(dish)
...
('spam', 'ham', 'eggs', 'bacon')
('sausage', 'onions', None, None)

Attempt for that this is a deliberate language choice. The majority of times does loop through numbers in lower level languages, those numbers are used as indexes in a sequence. For the cases one does actually needs the numbers, one should use the range built-in function - which returns an iterable with the desired range([start], end, [step]) input values.
More often, one does need both the items of a sequence and their index, in this case, one should use the builtn enumerateinstead:
for index, letter in enumerate("word"):
print index, letter
And finally, in C and derived languages (Java, PHP, Javascript, C#, Objective C), the for Syntax is just some (very rough) syntax sugar to a while loop - and you can just write the same while loop in Python.
Instead of:
for (start_expr, check_expr, incr_expr) { code_body} you do:
start_expr
while check_expr:
code_body
incr_expr
It works exactly the same.

for i in range(length):
#do something
What range is.

Related

How does this python enumerate script work and what makes it so fast? [duplicate]

What does for row_number, row in enumerate(cursor): do in Python?
What does enumerate mean in this context?
The enumerate() function adds a counter to an iterable.
So for each element in cursor, a tuple is produced with (counter, element); the for loop binds that to row_number and row, respectively.
Demo:
>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
... print elem
...
foo
bar
baz
>>> for count, elem in enumerate(elements):
... print count, elem
...
0 foo
1 bar
2 baz
By default, enumerate() starts counting at 0 but if you give it a second integer argument, it'll start from that number instead:
>>> for count, elem in enumerate(elements, 42):
... print count, elem
...
42 foo
43 bar
44 baz
If you were to re-implement enumerate() in Python, here are two ways of achieving that; one using itertools.count() to do the counting, the other manually counting in a generator function:
from itertools import count
def enumerate(it, start=0):
# return an iterator that adds a counter to each element of it
return zip(count(start), it)
and
def enumerate(it, start=0):
count = start
for elem in it:
yield (count, elem)
count += 1
The actual implementation in C is closer to the latter, with optimisations to reuse a single tuple object for the common for i, ... unpacking case and using a standard C integer value for the counter until the counter becomes too large to avoid using a Python integer object (which is unbounded).
It's a builtin function that returns an object that can be iterated over. See the documentation.
In short, it loops over the elements of an iterable (like a list), as well as an index number, combined in a tuple:
for item in enumerate(["a", "b", "c"]):
print item
prints
(0, "a")
(1, "b")
(2, "c")
It's helpful if you want to loop over a sequence (or other iterable thing), and also want to have an index counter available. If you want the counter to start from some other value (usually 1), you can give that as second argument to enumerate.
I am reading a book (Effective Python) by Brett Slatkin and he shows another way to iterate over a list and also know the index of the current item in the list but he suggests that it is better not to use it and to use enumerate instead.
I know you asked what enumerate means, but when I understood the following, I also understood how enumerate makes iterating over a list while knowing the index of the current item easier (and more readable).
list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
letter = list_of_letters[i]
print (i, letter)
The output is:
0 a
1 b
2 c
I also used to do something, even sillier before I read about the enumerate function.
i = 0
for n in list_of_letters:
print (i, n)
i += 1
It produces the same output.
But with enumerate I just have to write:
list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
print (i, letter)
As other users have mentioned, enumerate is a generator that adds an incremental index next to each item of an iterable.
So if you have a list say l = ["test_1", "test_2", "test_3"], the list(enumerate(l)) will give you something like this: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].
Now, when this is useful? A possible use case is when you want to iterate over items, and you want to skip a specific item that you only know its index in the list but not its value (because its value is not known at the time).
for index, value in enumerate(joint_values):
if index == 3:
continue
# Do something with the other `value`
So your code reads better because you could also do a regular for loop with range but then to access the items you need to index them (i.e., joint_values[i]).
Although another user mentioned an implementation of enumerate using zip, I think a more pure (but slightly more complex) way without using itertools is the following:
def enumerate(l, start=0):
return zip(range(start, len(l) + start), l)
Example:
l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)
Output:
[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]
[(10, 'test_1'), (11, 'test_2'), (12, 'test_3')]
As mentioned in the comments, this approach with range will not work with arbitrary iterables as the original enumerate function does.
The enumerate function works as follows:
doc = """I like movie. But I don't like the cast. The story is very nice"""
doc1 = doc.split('.')
for i in enumerate(doc1):
print(i)
The output is
(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
I am assuming that you know how to iterate over elements in some list:
for el in my_list:
# do something
Now sometimes not only you need to iterate over the elements, but also you need the index for each iteration. One way to do it is:
i = 0
for el in my_list:
# do somethings, and use value of "i" somehow
i += 1
However, a nicer way is to user the function "enumerate". What enumerate does is that it receives a list, and it returns a list-like object (an iterable that you can iterate over) but each element of this new list itself contains 2 elements: the index and the value from that original input list:
So if you have
arr = ['a', 'b', 'c']
Then the command
enumerate(arr)
returns something like:
[(0,'a'), (1,'b'), (2,'c')]
Now If you iterate over a list (or an iterable) where each element itself has 2 sub-elements, you can capture both of those sub-elements in the for loop like below:
for index, value in enumerate(arr):
print(index,value)
which would print out the sub-elements of the output of enumerate.
And in general you can basically "unpack" multiple items from list into multiple variables like below:
idx,value = (2,'c')
print(idx)
print(value)
which would print
2
c
This is the kind of assignment happening in each iteration of that loop with enumerate(arr) as iterable.
the enumerate function calculates an elements index and the elements value at the same time. i believe the following code will help explain what is going on.
for i,item in enumerate(initial_config):
print(f'index{i} value{item}')

Is there any reason to prefer dict() to {} in Python? [duplicate]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 months ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I understand that they are both essentially the same thing, but in terms of style, which is the better (more Pythonic) one to use to create an empty list or dict?
In terms of speed, it's no competition for empty lists/dicts:
>>> from timeit import timeit
>>> timeit("[]")
0.040084982867934334
>>> timeit("list()")
0.17704233359267718
>>> timeit("{}")
0.033620194745424214
>>> timeit("dict()")
0.1821558326547077
and for non-empty:
>>> timeit("[1,2,3]")
0.24316302770330367
>>> timeit("list((1,2,3))")
0.44744206316727286
>>> timeit("list(foo)", setup="foo=(1,2,3)")
0.446036018543964
>>> timeit("{'a':1, 'b':2, 'c':3}")
0.20868602015059423
>>> timeit("dict(a=1, b=2, c=3)")
0.47635635255323905
>>> timeit("dict(bar)", setup="bar=[('a', 1), ('b', 2), ('c', 3)]")
0.9028228448029267
Also, using the bracket notation lets you use list and dictionary comprehensions, which may be reason enough.
In my opinion [] and {} are the most pythonic and readable ways to create empty lists/dicts.
Be wary of set()'s though, for example:
this_set = {5}
some_other_set = {}
Can be confusing. The first creates a set with one element, the second creates an empty dict and not a set.
The dict literal might be a tiny bit faster as its bytecode is shorter:
In [1]: import dis
In [2]: a = lambda: {}
In [3]: b = lambda: dict()
In [4]: dis.dis(a)
1 0 BUILD_MAP 0
3 RETURN_VALUE
In [5]: dis.dis(b)
1 0 LOAD_GLOBAL 0 (dict)
3 CALL_FUNCTION 0
6 RETURN_VALUE
Same applies to the list vs []
Be careful list() and [] works differently:
>>> def a(p):
... print(id(p))
...
>>> for r in range(3):
... a([])
...
139969725291904
139969725291904
139969725291904
>>> for r in range(3):
... a(list())
...
139969725367296
139969725367552
139969725367616
list() always creates a new object on the heap, but [] can reuse memory cells in many situations.
IMHO, using list() and dict() makes your Python look like C. Ugh.
In the case of difference between [] and list(), there is a pitfall that I haven't seen anyone else point out.
If you use a dictionary as a member of the list, the two will give entirely different results:
In [1]: foo_dict = {"1":"foo", "2":"bar"}
In [2]: [foo_dict]
Out [2]: [{'1': 'foo', '2': 'bar'}]
In [3]: list(foo_dict)
Out [3]: ['1', '2']
A difference between list() and [] not mentioned by anyone, is that list() will convert, for example a tuple, into a list. And [] will put said tuple into a list:
a_tuple = (1, 2, 3, 4)
test_list = list(a_tuple) # returns [1, 2, 3, 4]
test_brackets = [a_tuple] # returns [(1, 2, 3, 4)]
There is no such difference between list() and [] but if you use it with iterators, it gives us:
nums = [1,2,3,4,5,6,7,8]
In: print([iter(nums)])
Out: [<list_iterator object at 0x03E4CDD8>]
In: print(list(iter(nums)))
Out: [1, 2, 3, 4, 5, 6, 7, 8]
there is one difference in behavior between [] and list() as example below shows. we need to use list() if we want to have the list of numbers returned, otherwise we get a map object! No sure how to explain it though.
sth = [(1,2), (3,4),(5,6)]
sth2 = map(lambda x: x[1], sth)
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>
sth2 = [map(lambda x: x[1], sth)]
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>
type(sth2) # list
type(sth2[0]) # map
sth2 = list(map(lambda x: x[1], sth))
print(sth2) #[2, 4, 6]
type(sth2) # list
type(sth2[0]) # int
One of the other differences between a list() and []
list_1 = ["Hello World"] # is a list of the word "Hello World"
list_2 = list("Hello World") # is a list of letters 'H', 'e', 'l'...
Something to keep in mind...
A box bracket pair denotes one of a list object, or an index subscript, like my_List[x].
A curly brace pair denotes a dictionary object.
a_list = ['on', 'off', 1, 2]
a_dict = { on: 1, off: 2 }

Return index in Python "in" operator [duplicate]

Given a list ["foo", "bar", "baz"] and an item in the list "bar", how do I get its index 1?
>>> ["foo", "bar", "baz"].index("bar")
1
See the documentation for the built-in .index() method of the list:
list.index(x[, start[, end]])
Return zero-based index in the list of the first item whose value is equal to x. Raises a ValueError if there is no such item.
The optional arguments start and end are interpreted as in the slice notation and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the start argument.
Caveats
Linear time-complexity in list length
An index call checks every element of the list in order, until it finds a match. If the list is long, and if there is no guarantee that the value will be near the beginning, this can slow down the code.
This problem can only be completely avoided by using a different data structure. However, if the element is known to be within a certain part of the list, the start and end parameters can be used to narrow the search.
For example:
>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514
The second call is orders of magnitude faster, because it only has to search through 10 elements, rather than all 1 million.
Only the index of the first match is returned
A call to index searches through the list in order until it finds a match, and stops there. If there could be more than one occurrence of the value, and all indices are needed, index cannot solve the problem:
>>> [1, 1].index(1) # the `1` index is not found.
0
Instead, use a list comprehension or generator expression to do the search, with enumerate to get indices:
>>> # A list comprehension gives a list of indices directly:
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> # A generator comprehension gives us an iterable object...
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> # which can be used in a `for` loop, or manually iterated with `next`:
>>> next(g)
0
>>> next(g)
2
The list comprehension and generator expression techniques still work if there is only one match, and are more generalizable.
Raises an exception if there is no match
As noted in the documentation above, using .index will raise an exception if the searched-for value is not in the list:
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
If this is a concern, either explicitly check first using item in my_list, or handle the exception with try/except as appropriate.
The explicit check is simple and readable, but it must iterate the list a second time. See What is the EAFP principle in Python? for more guidance on this choice.
The majority of answers explain how to find a single index, but their methods do not return multiple indexes if the item is in the list multiple times. Use enumerate():
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
The index() function only returns the first occurrence, while enumerate() returns all occurrences.
As a list comprehension:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Here's also another small solution with itertools.count() (which is pretty much the same approach as enumerate):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
This is more efficient for larger lists than using enumerate():
$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop
To get all indexes:
indexes = [i for i, x in enumerate(xs) if x == 'foo']
index() returns the first index of value!
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
def all_indices(value, qlist):
indices = []
idx = -1
while True:
try:
idx = qlist.index(value, idx+1)
indices.append(idx)
except ValueError:
break
return indices
all_indices("foo", ["foo","bar","baz","foo"])
A problem will arise if the element is not in the list. This function handles the issue:
# if element is found it returns index of element else returns None
def find_element_in_list(element, list_element):
try:
index_element = list_element.index(element)
return index_element
except ValueError:
return None
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
You have to set a condition to check if the element you're searching is in the list
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
If you want all indexes, then you can use NumPy:
import numpy as np
array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)
It is clear, readable solution.
All of the proposed functions here reproduce inherent language behavior but obscure what's going on.
[i for i in range(len(mylist)) if mylist[i]==myterm] # get the indices
[each for each in mylist if each==myterm] # get the items
mylist.index(myterm) if myterm in mylist else None # get the first index and fail quietly
Why write a function with exception handling if the language provides the methods to do what you want itself?
Finding the index of an item given a list containing it in Python
For a list ["foo", "bar", "baz"] and an item in the list "bar", what's the cleanest way to get its index (1) in Python?
Well, sure, there's the index method, which returns the index of the first occurrence:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
There are a couple of issues with this method:
if the value isn't in the list, you'll get a ValueError
if more than one of the value is in the list, you only get the index for the first one
No values
If the value could be missing, you need to catch the ValueError.
You can do so with a reusable definition like this:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
And use it like this:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
And the downside of this is that you will probably have a check for if the returned value is or is not None:
result = index(a_list, value)
if result is not None:
do_something(result)
More than one value in the list
If you could have more occurrences, you'll not get complete information with list.index:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
You might enumerate into a list comprehension the indexes:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
If you have no occurrences, you can check for that with boolean check of the result, or just do nothing if you loop over the results:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Better data munging with pandas
If you have pandas, you can easily get this information with a Series object:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
A comparison check will return a series of booleans:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Pass that series of booleans to the series via subscript notation, and you get just the matching members:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
If you want just the indexes, the index attribute returns a series of integers:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
And if you want them in a list or tuple, just pass them to the constructor:
>>> list(series[series == 'bar'].index)
[1, 3]
Yes, you could use a list comprehension with enumerate too, but that's just not as elegant, in my opinion - you're doing tests for equality in Python, instead of letting builtin code written in C handle it:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
Is this an XY problem?
The XY problem is asking about your attempted solution rather than your actual problem.
Why do you think you need the index given an element in a list?
If you already know the value, why do you care where it is in a list?
If the value isn't there, catching the ValueError is rather verbose - and I prefer to avoid that.
I'm usually iterating over the list anyways, so I'll usually keep a pointer to any interesting information, getting the index with enumerate.
If you're munging data, you should probably be using pandas - which has far more elegant tools than the pure Python workarounds I've shown.
I do not recall needing list.index, myself. However, I have looked through the Python standard library, and I see some excellent uses for it.
There are many, many uses for it in idlelib, for GUI and text parsing.
The keyword module uses it to find comment markers in the module to automatically regenerate the list of keywords in it via metaprogramming.
In Lib/mailbox.py it seems to be using it like an ordered mapping:
key_list[key_list.index(old)] = new
and
del key_list[key_list.index(key)]
In Lib/http/cookiejar.py, seems to be used to get the next month:
mon = MONTHS_LOWER.index(mon.lower())+1
In Lib/tarfile.py similar to distutils to get a slice up to an item:
members = members[:members.index(tarinfo)]
In Lib/pickletools.py:
numtopop = before.index(markobject)
What these usages seem to have in common is that they seem to operate on lists of constrained sizes (important because of O(n) lookup time for list.index), and they're mostly used in parsing (and UI in the case of Idle).
While there are use-cases for it, they are fairly uncommon. If you find yourself looking for this answer, ask yourself if what you're doing is the most direct usage of the tools provided by the language for your use-case.
Getting all the occurrences and the position of one or more (identical) items in a list
With enumerate(alist) you can store the first element (n) that is the index of the list when the element x is equal to what you look for.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Let's make our function findindex
This function takes the item and the list as arguments and return the position of the item in the list, like we saw before.
def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]
print(indexlist("1", "010101010"))
Output
[1, 3, 5, 7]
Simple
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Output:
0
4
me = ["foo", "bar", "baz"]
me.index("bar")
You can apply this for any member of the list to get their index
All indexes with the zip function:
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')
Simply you can go with
a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']
res = [[x[0] for x in a].index(y) for y in b]
Another option
>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
... indices.append(a.index(b,offset))
... offset = indices[-1]+1
...
>>> indices
[0, 3]
>>>
And now, for something completely different...
... like confirming the existence of the item before getting the index. The nice thing about this approach is the function always returns a list of indices -- even if it is an empty list. It works with strings as well.
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
When pasted into an interactive python window:
Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
... """Always returns a list containing the indices of val in the_list"""
... retval = []
... last = 0
... while val in the_list[last:]:
... i = the_list[last:].index(val)
... retval.append(last + i)
... last += i + 1
... return retval
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
Update
After another year of heads-down python development, I'm a bit embarrassed by my original answer, so to set the record straight, one can certainly use the above code; however, the much more idiomatic way to get the same behavior would be to use list comprehension, along with the enumerate() function.
Something like this:
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
return [index for index, value in enumerate(l) if value == val]
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
Which, when pasted into an interactive python window yields:
Python 2.7.14 |Anaconda, Inc.| (default, Dec 7 2017, 11:07:58)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
... """Always returns a list containing the indices of val in the_list"""
... return [index for index, value in enumerate(l) if value == val]
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
And now, after reviewing this question and all the answers, I realize that this is exactly what FMc suggested in his earlier answer. At the time I originally answered this question, I didn't even see that answer, because I didn't understand it. I hope that my somewhat more verbose example will aid understanding.
If the single line of code above still doesn't make sense to you, I highly recommend you Google 'python list comprehension' and take a few minutes to familiarize yourself. It's just one of the many powerful features that make it a joy to use Python to develop code.
Here's a two-liner using Python's index() function:
LIST = ['foo' ,'boo', 'shoo']
print(LIST.index('boo'))
Output: 1
A variant on the answer from FMc and user7177 will give a dict that can return all indices for any entry:
>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>>
You could also use this as a one liner to get all indices for a single entry. There are no guarantees for efficiency, though I did use set(a) to reduce the number of times the lambda is called.
Finding index of item x in list L:
idx = L.index(x) if (x in L) else -1
This solution is not as powerful as others, but if you're a beginner and only know about forloops it's still possible to find the first index of an item while avoiding the ValueError:
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
There is a chance that that value may not be present so to avoid this ValueError, we can check if that actually exists in the list .
list = ["foo", "bar", "baz"]
item_to_find = "foo"
if item_to_find in list:
index = list.index(item_to_find)
print("Index of the item is " + str(index))
else:
print("That word does not exist")
List comprehension would be the best option to acquire a compact implementation in finding the index of an item in a list.
a_list = ["a", "b", "a"]
print([index for (index , item) in enumerate(a_list) if item == "a"])
It just uses the python function array.index() and with a simple Try / Except it returns the position of the record if it is found in the list and return -1 if it is not found in the list (like on JavaScript with the function indexOf()).
fruits = ['apple', 'banana', 'cherry']
try:
pos = fruits.index("mango")
except:
pos = -1
In this case "mango" is not present in the list fruits so the pos variable is -1, if I had searched for "cherry" the pos variable would be 2.
There is a more functional answer to this.
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
More generic form:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
For one comparable
# Throws ValueError if nothing is found
some_list = ['foo', 'bar', 'baz'].index('baz')
# some_list == 2
Custom predicate
some_list = [item1, item2, item3]
# Throws StopIteration if nothing is found
# *unless* you provide a second parameter to `next`
index_of_value_you_like = next(
i for i, item in enumerate(some_list)
if item.matches_your_criteria())
Finding index of all items by predicate
index_of_staff_members = [
i for i, user in enumerate(users)
if user.is_staff()]
Python index() method throws an error if the item was not found. So instead you can make it similar to the indexOf() function of JavaScript which returns -1 if the item was not found:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
new_list.append(item[0])
print(new_list)
try:
location= new_list.index(name)
except:
location=-1
print (location)
This accounts for if the string is not in the list too, if it isn't in the list then location = -1
If you are going to find an index once then using "index" method is fine. However, if you are going to search your data more than once then I recommend using bisect module. Keep in mind that using bisect module data must be sorted. So you sort data once and then you can use bisect.
Using bisect module on my machine is about 20 times faster than using index method.
Here is an example of code using Python 3.8 and above syntax:
import bisect
from timeit import timeit
def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)
data = list(range(1000))
# value to search
value = 666
# times to test
ttt = 1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)
print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
Output:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
For those coming from another language like me, maybe with a simple loop it's easier to understand and use it:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
I am thankful for So what exactly does enumerate do?. That helped me to understand.
Since Python lists are zero-based, we can use the zip built-in function as follows:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
where "haystack" is the list in question and "needle" is the item to look for.
(Note: Here we are iterating using i to get the indexes, but if we need rather to focus on the items we can switch to j.)

Can you manually sort a list in python?

If I had a list of words, e.g.
words = ['apple', 'boat', 'cat']
And I also had a list of numbers, e.g.
num = [1, 2, 0]
Is there a way to then sort the first list according to the numbers in the second list? I.e. The index of 'apple' is 0, so it should be last in the list, the index of 'boat' is 1, so it should be first, etc.
words = ['apple','boat','cat']
num = [1,2,0]
print([words[current_index] for current_index in num])
Output
['boat', 'cat', 'apple']
The list comprehension method will work both on Python 2.x and 3.x.
Though I would NOT recommend this, you can write this more succinctly like this
print(map(words.__getitem__, num))
The same thing can be written in Python 3.x, like this
print(list(map(words.__getitem__, num)))
Using operator.itemgetter:
>>> words = ['apple','boat','cat']
>>> num = [1,2,0]
>>> import operator
>>> operator.itemgetter(*num)(words)
('boat', 'cat', 'apple')
Since you know indexes won't be repeated in the second list, and you know they'll be the same length in you can create a for loop:
words_b = []
for n in num:
words_b.append(words[n])
words = words_b
But thefourtheye already did this in a more compact way. This one's just a little more readable if you are not well-versed in Python.

Python - Count elements in list [duplicate]

This question already has answers here:
How do I get the number of elements in a list (length of a list) in Python?
(11 answers)
Closed 6 years ago.
I am trying to find a simple way of getting a count of the number of elements in a list:
MyList = ["a", "b", "c"]
I want to know there are 3 elements in this list.
len()
>>> someList=[]
>>> print len(someList)
0
just do len(MyList)
This also works for strings, tuples, dict objects.
len(myList) should do it.
len works with all the collections, and strings too.
len()
it will count the element in the list, tuple and string and dictionary,
eg.
>>> mylist = [1,2,3] #list
>>> len(mylist)
3
>>> word = 'hello' # string
>>> len(word)
5
>>> vals = {'a':1,'b':2} #dictionary
>>> len(vals)
2
>>> tup = (4,5,6) # tuple
>>> len(tup)
3
To learn Python you can use byte of python , it is best ebook for python beginners.
To find count of unique elements of list use the combination of len() and set().
>>> ls = [1, 2, 3, 4, 1, 1, 2]
>>> len(ls)
7
>>> len(set(ls))
4
You can get element count of list by following two ways:
>>> l = ['a','b','c']
>>> len(l)
3
>>> l.__len__()
3
Len won't yield the total number of objects in a nested list (including multidimensional lists). If you have numpy, use size(). Otherwise use list comprehensions within recursion.

Categories

Resources