我有一个列表,我想找到具有最低数量' *'的元素。
mylist = ['12*3','12345**6','11234']
所以这个小测试的答案是' 11234'
这种方法有效,但速度很慢(我正在处理大量的基因组数据:
sorted(mylist, key = lambda x: x.count('*'))[0]
这不那么雄辩,但有效:
values = map(lambda x: x.count('*'), mylist)
print mylist[values.index(min(values))]
有更好的方法吗? 我试图做一个schwartzian变换,但无法弄清楚。
答案 0 :(得分:7)
您可以将min
与key
参数一起使用:
>>> mylist = ['12*3','12345**6','11234']
>>> min(mylist, key=lambda x: x.count('*'))
'11234'
key
是一个函数,在iterable上的每个项目上调用,以与sorted
中相同的方式指定排序。
上述方法将导致 O(n)时间复杂度,其中排序为 O(n log n)。
更新:如果您的字符串非常长,那么您可以在循环中计算*
的出现次数,并在count与当前最小值相同时拒绝该字符串。如果找到出现0次的字符串,您也可以终止搜索:
def find(l):
min_item = None
min_val = float('inf')
for x in l:
current = 0
for c in x:
current += (c == '*')
if current >= min_val:
break
else:
# Found new minimum, update
min_item = x
min_val = current
# Can't get lower than 0
if min_val == 0:
break
return min_item
print(find(['12*3','11234', '12345**6', '1'])) # '11234'
答案 1 :(得分:1)
您可以通过为key
而不是lambda
创建单独的函数来进一步提高性能,因为 lambda函数很慢。例如:
def get_asterisk_count(my_string):
return my_string.count('*')
mylist = ['12*3','12345**6','11234']
min(mylist, key=get_asterisk_count)
以下是timeit
统计信息:
使用lambda
功能:1.25 usec
mquadri$ python -m "timeit" -s "mylist = ['12*3','12345**6','11234']" "min(mylist, key=lambda x: x.count('*'))"
1000000 loops, best of 3: 1.25 usec per loop
使用单独的功能:1.19 usec
mquadri$ python -m "timeit" -s "mylist = ['12*3','12345**6','11234']" "def get_asterisk_count(my_string): return my_string.count('*')" "min(mylist, key=get_asterisk_count)"
1000000 loops, best of 3: 1.19 usec per loop