Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python idiom: List comprehension with limit of items

I'm basically trying to do this (pseudo code, not valid python):

limit = 10
results = [xml_to_dict(artist) for artist in xml.findall('artist') while limit--]

So how could I code this in a concise and efficient way? The XML file can contain anything between 0 and 50 artists, and I can't control how many to get at a time, and AFAIK, there's no XPATH expression to say something like "get me up to 10 nodes".

Thanks!

like image 958
adamJLev Avatar asked Aug 20 '10 20:08

adamJLev


People also ask

Is there a limit to the number of items in a list Python?

Maximum length of a list is platform dependent and depends upon address space and/or RAM. The maxsize constant defined in sys module returns 263-1 on 64 bit system. The largest positive integer supported by the platform's Py_ssize_t type, is the maximum size lists, strings, dicts, and many other containers can have.

How much faster are list comprehensions?

The list comprehension is 50% faster.

Can you do list comprehension with strings?

List comprehension works with string lists also. The following creates a new list of strings that contains 'a'. Above, the expression if 'a' in s returns True if an element contains a character 'a'. So, the new list will include names that contain 'a'.


2 Answers

Are you using lxml? You could use XPath to limit the items in the query level, e.g.

>>> from lxml import etree
>>> from io import StringIO
>>> xml = etree.parse(StringIO('<foo><bar>1</bar><bar>2</bar><bar>4</bar><bar>8</bar></foo>'))
>>> [bar.text for bar in xml.xpath('bar[position()<=3]')]
['1', '2', '4']

You could also use itertools.islice to limit any iterable, e.g.

>>> from itertools import islice
>>> [bar.text for bar in islice(xml.iterfind('bar'), 3)]
['1', '2', '4']
>>> [bar.text for bar in islice(xml.iterfind('bar'), 5)]
['1', '2', '4', '8']
like image 84
kennytm Avatar answered Oct 03 '22 22:10

kennytm


Assuming that xml is an ElementTree object, the findall() method returns a list, so just slice that list:

limit = 10
limited_artists = xml.findall('artist')[:limit]
results = [xml_to_dict(artist) for artist in limited_artists]
like image 45
jathanism Avatar answered Oct 03 '22 23:10

jathanism