[英]Finding the index of the value which is the min or max in Python
我有一个形式的结构:
>>> items
[([[0, 1], [2, 20]], 'zz', ''), ([[1, 3], [5, 29], [50, 500]], 'a', 'b')]
每个元组中的第一项是范围列表,我想制作一个生成器,根据起始索引按升序为我提供范围。
由于范围列表已经按其起始索引排序,因此此操作很简单:它只是一个排序合并。 我希望以良好的计算效率来做到这一点,所以我认为隐式跟踪我的合并的 state 的一种好方法是简单地弹出元组列表的前面,该元组的起始索引在其范围列表。
我可以使用min()
来获得[0, 1]
这是我想要的第一个,但我如何获得它的索引?
我有这个:
[ min (items[i][0]) for i in range(len(items)) ]
这给了我每个列表中的第一个项目,然后我可以min()
以某种方式进行,但是一旦任何列表变空它就会失败,而且还不清楚如何让索引在不看的情况下使用pop()
备份在列表中。
总结一下:想要构建为我返回的生成器:
([0,1], 'zz', '')
([1,3], 'a', 'b')
([2,20], 'zz', '')
([5,29], 'a', 'b')
([50,500], 'a', 'b')
或者更有效地,我只需要这些数据:
[0, 1, 0, 1, 1]
(我想取前面的元组的索引)
from operator import itemgetter
index, element = max(enumerate(items), key=itemgetter(1))
返回items
最大元素的索引和元素本身。
此方法查找任何可迭代的最大元素的索引,并且不需要任何外部导入:
def argmax(iterable):
return max(enumerate(iterable), key=lambda x: x[1])[0]
列表最大值的索引:
def argmax(lst):
return lst.index(max(lst))
如果lst中存在重复的最大值,则返回找到的第一个最大值的索引。
这有效:
by_index = ([sub_index, list_index] for list_index, list_item in
enumerate(items) for sub_index in list_item[0])
[item[1] for item in sorted(by_index)]
得到:
[0, 1, 0, 1, 1]
详细。 发电机:
by_index = ([sub_index, list_index] for list_index, list_item in
enumerate(items) for sub_index in list_item[0])
list(by_index)
[[[0, 1], 0], [[2, 20], 0], [[1, 3], 1], [[5, 29], 1], [[50, 500], 1]]
因此,唯一需要的是排序并获得所需的索引:
[item[1] for item in sorted(by_index)]
获得argmax的另一种方法是:
def argmax(lst):
return max(range(len(lst)), key=lst.__getitem__)
所以这是一个真正快速简便的方法来获得您正在寻找的高效版本:
a = []
count = 0
for i in items:
for x in i[0]:
#place a list with the index next to it in list a for sorting
a.append((x,count))
#continually grabs the smallest list and returns the index it was in
sort = [a.pop(a.index(min(a)))[1] for i in range(len(a))]
这是与您的项目,以显示它的工作原理:
>>> items = [([[0, 1], [2, 20]], 'zz', ''), ([[1, 3], [5, 29], [50, 500]], 'a', 'b')]
>>> a = []
>>> count = 0
>>> for i in items:
... for x in i[0]:
... a.append((x,count))
... count += 1
...
>>> sort = [a.pop(a.index(min(a)))[1] for i in range(len(a))]
>>> sort
[0, 1, 0, 1, 1]
如果您不尝试使用内部范围列表进行排序的事实,这很容易
sorted(sum([ [(rng,) + i[1:] for rng in i[0]] for i in items ], []), lambda i: i[0][0])
听起来你想要一个返回最小值索引的函数
def min_idx(l, key=lambda x: x):
min_i, min_key = None, float('inf')
for i, v in enumerate(l):
key_v = key(v)
if key_v < min_key:
mini_i = i
min_key = key_v
return min_i
def merge_items(items):
res = []
while True:
i = min_idx(items, key=lambda i: i[0][0][0])
item = items[i]
res.append((item[0][0],) + item[1:])
return res
我不确定发生了什么,但我认为每个人都有点不合时宜。 我会把它归咎于做一个糟糕的工作来解释我正试图解决的问题。 无论如何,这是我得到了多少:
items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
这让我大部分都在那里,但剩下要处理的是处理一个列表已经用尽的情况。 一旦处理好它应该是微不足道的,使它成为一个生成器,因为我可以把它放在一个循环中并在其中产生,并且也希望没有太多的工作,这可以适应于执行有效的排序合并生成器。
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[0, 1]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[1, 3]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
[2, 20]
>>> items[min(range(len(items)), key = lambda x: items[x][0][0])][0].pop(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
IndexError: list index out of range
更新:
将剩余有效物品的适当子集组装成min
票是票。
def next_value_in_sections(sections):
while 1:
idxs = []
for i, x in enumerate(sections):
if x[0]:
idxs.append(i)
print idxs
if not idxs:
break
j = min(idxs, key=lambda x: sections[x][0][0])
yield (sections[j][0].pop(0), j)
items = [([[0, 1], [2, 20]], 'zz', ''),
([[1, 3], [5, 29], [50, 500]], 'a', 'b')]
x = next_value_in_sections(items)
for i in x:
print i
执行:
$ python test.py
[0, 1]
([0, 1], 0)
[0, 1]
([1, 3], 1)
[0, 1]
([2, 20], 0)
[1]
([5, 29], 1)
[1]
([50, 500], 1)
[]
我会注意到这仍然可以改进,每次迭代都会重建idxs列表。 它不需要,但这样做并没有改善渐近界限...当然,人们不得不怀疑我们是否真的关心性能,是否使用lambda也是一个好主意,尽管我真的不这样做看看周围的方式,而不分开min
,这只是疯狂的下降。
最简单最有效的方式(O(n))
arg_max, maximum = max(list(enumerate(nums)), key=lambda x: x[1]) # Returns both the maximum element and it's index
另一种选择:
max(zip(lst, range(len(lst))))[0]
这似乎是最快的,连同
max(range(len(lst)), key=lst.__getitem__)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.