Python equivalent of Haskell's [1..] (to index a list)
Question:
I have a list of elements in python. I don’t know the number of elements in the list. I would like to add indexes to the list.
In Haskell, I could do the following
zip [1..] "abcdefghijklmnop"
[(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j'),(11,'k'),(12,'l'),(13,'m'),(14,'n'),(15,'o'),(16,'p')]
Now imagine that the string was of unknown size. This would still work in Haskell, and the integer list gives as many integers as necessary until the string runs out.
How would one do the equivalent in Python?
I have tried this:
s = "abcdefghijklmnop"
indexedlist = []
for i,c in enumerate(s):
indexedlist.append((i,c))
>>> indexedlist
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
And it works, but I’m wondering if there is a shorter/cleaner way, since it is 4 lines of code and feels much.
Answers:
You can use the range
function with zip
.
For Python 2:
>>> s = "abcdefghijklmnop"
>>> zip(range(16),s)
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
For Python 3:
>>> s = "abcdefghijklmnop"
>>> list(zip(range(16),s))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
Just do list(enumerate(s))
. This iterates over the enumerate
object and converts it to a list
.
You can simplify it with a list comprehension:
>>> [i for i in enumerate(s)]
Using enumerate
is definitely the way to go, but here is a little bit more functional solution with toolz:
from toolz.itertoolz import iterate, zip
zip(iterate(lambda x: x + 1, 0), "abcdefghijklmnop")
lists in Haskell are lazy, indeed, these could also work with an "infinite list".
Therefore a more semantically equivalent Python fragment would just be:
enumerate(l, start=1)
if you then enumerate over this result, it will enumerate over the list l
and produce 2-tuples when necessary.
I have a list of elements in python. I don’t know the number of elements in the list. I would like to add indexes to the list.
In Haskell, I could do the following
zip [1..] "abcdefghijklmnop"
[(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i'),(10,'j'),(11,'k'),(12,'l'),(13,'m'),(14,'n'),(15,'o'),(16,'p')]
Now imagine that the string was of unknown size. This would still work in Haskell, and the integer list gives as many integers as necessary until the string runs out.
How would one do the equivalent in Python?
I have tried this:
s = "abcdefghijklmnop"
indexedlist = []
for i,c in enumerate(s):
indexedlist.append((i,c))
>>> indexedlist
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
And it works, but I’m wondering if there is a shorter/cleaner way, since it is 4 lines of code and feels much.
You can use the range
function with zip
.
For Python 2:
>>> s = "abcdefghijklmnop"
>>> zip(range(16),s)
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
For Python 3:
>>> s = "abcdefghijklmnop"
>>> list(zip(range(16),s))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h'), (8, 'i'), (9, 'j'), (10, 'k'), (11, 'l'), (12, 'm'), (13, 'n'), (14, 'o'), (15, 'p')]
Just do list(enumerate(s))
. This iterates over the enumerate
object and converts it to a list
.
You can simplify it with a list comprehension:
>>> [i for i in enumerate(s)]
Using enumerate
is definitely the way to go, but here is a little bit more functional solution with toolz:
from toolz.itertoolz import iterate, zip
zip(iterate(lambda x: x + 1, 0), "abcdefghijklmnop")
lists in Haskell are lazy, indeed, these could also work with an "infinite list".
Therefore a more semantically equivalent Python fragment would just be:
enumerate(l, start=1)
if you then enumerate over this result, it will enumerate over the list l
and produce 2-tuples when necessary.