Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从现有列表创建较小的列表_Python_List_Itertools - Fatal编程技术网

Python 从现有列表创建较小的列表

Python 从现有列表创建较小的列表,python,list,itertools,Python,List,Itertools,我有一个列表,如下所示: >>> list1 = ['Mary','had','a','little','lamb','which','was','very','naughty'] 我需要从list1中创建另一个列表(list2),该列表是通过迭代list1并找到元素little,然后将little和little之后的每个元素添加到list2中创建的 我仔细阅读了一下,发现itertools的dropwhile正好满足我的需求 >>> from iterto

我有一个列表,如下所示:

>>> list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
我需要从
list1
中创建另一个列表(
list2
),该列表是通过迭代
list1
并找到元素little,然后将littlelittle之后的每个元素添加到
list2
中创建的

我仔细阅读了一下,发现itertools的dropwhile正好满足我的需求

>>> from itertools import dropwhile
>>> list2 = list(dropwhile(lambda l: 'little' not in l, list1))
>>> list2
['little', 'lamb', 'which', 'was', 'very', 'naughty']
它完全符合我的要求

但是,现在我还需要指定结束元素。因此我需要一个从littlevery的元素列表,包括以下两个元素:

>>>list3
['little', 'lamb', 'which', 'was', 'very']

如何使用类似的方法来实现这一点?

不使用itertools的简单方法可能类似于:

start = list1.index("little")
end = list1.index("very")
list3 = list1[start:end+1]
或者你可以简单地写为:

list3 = list1[list1.index("little"):list1.index("very")+1]

你可以做列表切片

>>> list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
>>> list1[list1.index('little'):list1.index('very')+1]
['little', 'lamb', 'which', 'was', 'very']

这应该可以做到:

 list1[list1.index('little'):-list1[::-1].index('very')]
结果:

['little', 'lamb', 'which', 'was', 'very']

我们在反向列表中搜索第二个关键字,然后在原始列表中使用负索引。

您可以使用自定义函数返回生成器:

def drop(iterable,start,end):

    for i,x in enumerate(iterable):
        if x==start :
            for y in iterable[i:]:
                if y!=end:
                    yield y
                else:
                    yield end
                    break
演示:

list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
print list(drop(list1,'little','very'))
['little', 'lamb', 'which', 'was', 'very']
请注意,此解决方案比使用
list.index
更快,因为它的顺序是O(n),并且使用了2次,但对于前面的函数,除了在
iterable[i://code>中的一个索引外,您还要在所有列表上迭代1次,因为它的顺序小于O(n),所以速度更快

为了更好地理解,请查看以下基准点:

from timeit import timeit

s1="""
list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
list1[list1.index("little"):list1.index("very")+1]
"""
s2="""
def drop(iterable,start,end):

    for i,x in enumerate(iterable):
        if x==start :
            for y in iterable[i:]:
                if y!=end:
                    yield y
                else:
                    yield end
                    break
list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
drop(list1,'little','very')
    """


print ' first: ' ,timeit(stmt=s1, number=1000000)
print 'second : ',timeit(stmt=s2, number=1000000)
结果:

 first:  5.87736296654
second :  5.01044201851 

如果您希望继续使用
itertools
(不关心性能):

输出:

['little', 'lamb', 'which', 'was', 'very']
如果您关心性能,您应该定义一个自定义逻辑(感谢@Kasra):


不假设“小”在“非常”之前的解决方案:

def列表_范围(ls、a、b):
a_i,b_i=ls.index(a),ls.index(b)
如果a_i
非常
也出现在
之前时,此操作失败。要将该过程
开始
作为
结束=列表1.index(“非常”)
的第二个参数处理。您应该认真定义边界线条件,因为您得到的答案很少会爆炸。是否始终保证元素的存在?它们是否每次只发生一次?如果没有,会发生什么。订单有保证吗?如果
非常
顽皮
之前,@luk32…我理解您的担忧,但我已经处理了这些边界线条件..我的目的是在处理所有这些边界线条件时获得逻辑..我只是想了解..这里的性能有什么问题。。?是的,每个
list
reverse
执行列表的完整扫描加上1…当探索非python解的性能只是为了理解..O(n)的顺序意味着什么?@Amistad在数学中,大O表示法描述了当参数趋向于某个特定值或无穷大readmore()时函数的限制行为
['little', 'lamb', 'which', 'was', 'very']
list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']

def drop(sequence,start,end):
    keep = False
    for item in sequence:
        if item == start:
            keep = True
        if keep and item == end:
            yield item
            break
        if keep:
            yield item

list3 = drop(list1, 'little', 'very')

print list(list3)
def list_range(ls, a, b):
    a_i, b_i = ls.index(a), ls.index(b)
    if a_i < b_i:
        return ls[a_i:b_i+1]
    else:
        return ls[a_i:b_i-1:-1]

list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
print list_range(list1, 'little', 'very')