代码之家  ›  专栏  ›  技术社区  ›  adamJLev

python习语:列表理解和项目限制

  •  4
  • adamJLev  · 技术社区  · 14 年前

    我基本上是想这样做(伪代码,不是有效的python):

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

    那么,我怎样才能用一种简洁有效的方式来编写代码呢? XML文件可以包含0到50个艺术家之间的任何内容,我无法控制一次要获取多少艺术家,而afaik,没有xpath表达式可以说“最多10个节点”。

    谢谢!

    5 回复  |  直到 10 年前
        1
  •  5
  •   jathanism    14 年前

    假设 xml 是一个 ElementTree 对象 findall() 方法返回一个列表,因此只需对该列表进行切片:

    limit = 10
    limited_artists = xml.findall('artist')[:limit]
    results = [xml_to_dict(artist) for artist in limited_artists]
    
        2
  •  6
  •   kennytm    14 年前

    你在用吗? lxml ?可以使用xpath限制查询级别中的项目,例如

    >>> 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']
    

    你也可以 use itertools.islice to limit any iterable ,例如

    >>> 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']
    
        3
  •  2
  •   S.Lott    14 年前
    limit = 10
    limited_artists = [artist in xml.findall('artist')][:limit]
    results = [xml_to_dict(artist) for limited_artists]
    
        4
  •  2
  •   Glenn Maynard    14 年前

    这就避免了切片的问题:它不会改变操作的顺序,也不会构建新的列表,如果您过滤列表理解,这对于大列表很重要。

    def first(it, count):
        it = iter(it)
        for i in xrange(0, count):
            yield next(it)
        raise StopIteration
    
    print [i for i in first(range(1000), 5)]
    

    它还可以与生成器表达式一起正常工作,因为内存使用,切片将丢失:

    exp = (i for i in first(xrange(1000000000), 10000000))
    for i in exp:
        print i
    
        5
  •  2
  •   smheidrich    10 年前

    对于其他所有因为试图限制从无限生成器返回的项而发现此问题的人:

    from itertools import takewhile
    ltd = takewhile(lambda x: x[0] < MY_LIMIT, enumerate( MY_INFINITE_GENERATOR ))
    # ^ This is still an iterator. 
    # If you want to materialize the items, e.g. in a list, do:
    ltd_m = list( ltd )
    # If you don't want the enumeration indices, you can strip them as usual:
    ltd_no_enum = [ v for i,v in ltd_m ]