从现有列表创建较小的列表
Creating a smaller list from an existing list
我有一个这样的列表:
>>> list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
我需要从 list1
中创建另一个列表 (list2
),这是通过遍历 list1
并找到元素 little 然后附加 little 和 little 之后的每个元素到 list2
.
仔细阅读了一下,发现 itertools 中的 dropwhile 正是为满足我的要求而制作的。
>>> from itertools import dropwhile
>>> list2 = list(dropwhile(lambda l: 'little' not in l, list1))
>>> list2
['little', 'lamb', 'which', 'was', 'very', 'naughty']
完全符合我的要求。
但是,现在我需要将结束元素指定为 well.So 我想要一个从 little 到 very[= 的元素列表34=] 两者都包含如下:
>>>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']
我们在反向列表中搜索第二个关键字,然后在原始列表中使用负索引。
您可以使用自定义函数,return生成器:
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:]
中对所有列表进行 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
(不关心性能):
from itertools import dropwhile
list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
list2 = list(dropwhile(lambda x: x!="little", list1))
list3 = list(dropwhile(lambda x: x!="very", reversed(list2)))
print list(reversed(list3))
输出:
['little', 'lamb', 'which', 'was', 'very']
如果你关心性能,你应该定义一个自定义逻辑(感谢@Kasra):
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)
不假设"little"在"very"之前的解决方案:
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')
我有一个这样的列表:
>>> list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
我需要从 list1
中创建另一个列表 (list2
),这是通过遍历 list1
并找到元素 little 然后附加 little 和 little 之后的每个元素到 list2
.
仔细阅读了一下,发现 itertools 中的 dropwhile 正是为满足我的要求而制作的。
>>> from itertools import dropwhile
>>> list2 = list(dropwhile(lambda l: 'little' not in l, list1))
>>> list2
['little', 'lamb', 'which', 'was', 'very', 'naughty']
完全符合我的要求。
但是,现在我需要将结束元素指定为 well.So 我想要一个从 little 到 very[= 的元素列表34=] 两者都包含如下:
>>>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']
我们在反向列表中搜索第二个关键字,然后在原始列表中使用负索引。
您可以使用自定义函数,return生成器:
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:]
中对所有列表进行 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
(不关心性能):
from itertools import dropwhile
list1 = ['Mary','had','a','little','lamb','which','was','very','naughty']
list2 = list(dropwhile(lambda x: x!="little", list1))
list3 = list(dropwhile(lambda x: x!="very", reversed(list2)))
print list(reversed(list3))
输出:
['little', 'lamb', 'which', 'was', 'very']
如果你关心性能,你应该定义一个自定义逻辑(感谢@Kasra):
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)
不假设"little"在"very"之前的解决方案:
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')