使用 Nones 查找最小元素及其在列表中的位置
Find minimum element and its position in list with Nones
我有一个数字列表和 None
是这样的:
l = [2., None, 3., 1., None, 2., None, 5.]
我想获得最小数字及其索引,而 None
应该被忽略。对于给定的示例,结果将是:
(1., 3)
当然,编写一个函数来执行我想要的操作很简单,但我更喜欢一些高效的内置方法或至少是高级方法。
我对 Python 3 的解决方案特别感兴趣,其中 min
函数不接受 None
作为参数。
l = [2., None, 3., 1., None, 2., None, 5.]
idx = l.index(min(x for x in l if x is not None))
print(l[idx], idx) # get value, and idx
输出
1.0 3
这是一种方法。
演示:
l = [2., None, 3., 1., None, 2., None, 5.]
l = [(v, i) for i, v in enumerate(l) if v is not None]
print( sorted(l, key=lambda x: x[0])[0] )
输出:
(1.0, 3)
value = min(l, key=lambda x: float('inf') if x is None else x)
index = l.index(value)
如果这是一个问题(即 l 中没有数字的情况),可能包括检查值是否为 inf
该方法通过简单地改变 min 比较值的方式避免了在内部构造新数组。
我可能会把它分成两部分:
m = min(x for x in l if x is not None)
s = (m, l.index(m)) # this will grab the first index
如果你想把list做成single pass + one liner的方案:
midx, mval = min(enumerate(x if x is not None else float('inf') for x in l), key=lambda i: i[1])
enumerate()
片段生成一个像这样的可迭代对象:
0 2.0
1 inf
2 3.0
3 1.0
4 inf
5 2.0
6 inf
7 5.0
然后调用 min()
并使用 enumerate()
return 和 lambda
检查 i[1]
索引中的值(例如 2.0, inf, ..., 5.0
).因此,最终的元组是 returned,仅使用一个生成器从原始列表到 "filter and replace" NoneType
索引进行一次迭代。
您可以定义一个转换函数并将其与 min
:
一起使用
lst = [2., None, 3., 1., None, 2., None, 5.]
def converter(x):
return x[1] if x[1] is not None else float('inf')
res = min(enumerate(lst), key=converter)[::-1]
(1.0, 3)
如果您喜欢使用第 3 方库,NumPy 中的等价物:
arr = np.array(lst).astype(float)
arr[np.isnan(arr)] = np.inf
res = arr.min(), arr.argmin()
或者,更有效地,您可以使用 np.nanargmin
:
arg = np.nanargmin(arr)
minval = arr[arg]
res = minval, arg
为什么结果应该是(1., 3),在1之后,2在后面
l = [2., None, 3., 1., None, 2., None, 5.]
bar = map(float, [e for e in l if isinstance(e, float)])
print (min(float(i) for i in bar))
min((v,i) for i,v in enumerate(l) if v is not None)
(1.0, 3) # (value, index)
您可以避免像这样使用 key
:
>>> import operator as op
>>> import itertools as it
>>> min(it.filterfalse(op.methodcaller('__contains__', None), zip(l, it.count())))
(1.0, 3)
最复杂的是在列表中替换,我认为:
import numpy as np
l = [2., None, 3., 1., None, 2., None, 5.]
#### function to replace in a list
def replaced(sequence, old, new):
return (new if x == old else x for x in sequence)
l=list(replaced(l,None,np.nan))
#### numpy specific function
position = np.nanargmin(l)
value = l[position]
print(position, value)
虽然我更喜欢接受的答案。
您可以在其中使用 NoneType 的演示代码:
lst = [2., None, 3., 1., None, 2., None, 5.]
def converter(x):
NoneType = type(None)
return x[1] if not isinstance(x[1], NoneType) else float('inf')
res = min(enumerate(lst), key=converter)[::-1]
print(res)
给予
(1.0, 3)
我有一个数字列表和 None
是这样的:
l = [2., None, 3., 1., None, 2., None, 5.]
我想获得最小数字及其索引,而 None
应该被忽略。对于给定的示例,结果将是:
(1., 3)
当然,编写一个函数来执行我想要的操作很简单,但我更喜欢一些高效的内置方法或至少是高级方法。
我对 Python 3 的解决方案特别感兴趣,其中 min
函数不接受 None
作为参数。
l = [2., None, 3., 1., None, 2., None, 5.]
idx = l.index(min(x for x in l if x is not None))
print(l[idx], idx) # get value, and idx
输出
1.0 3
这是一种方法。
演示:
l = [2., None, 3., 1., None, 2., None, 5.]
l = [(v, i) for i, v in enumerate(l) if v is not None]
print( sorted(l, key=lambda x: x[0])[0] )
输出:
(1.0, 3)
value = min(l, key=lambda x: float('inf') if x is None else x)
index = l.index(value)
如果这是一个问题(即 l 中没有数字的情况),可能包括检查值是否为 inf
该方法通过简单地改变 min 比较值的方式避免了在内部构造新数组。
我可能会把它分成两部分:
m = min(x for x in l if x is not None)
s = (m, l.index(m)) # this will grab the first index
如果你想把list做成single pass + one liner的方案:
midx, mval = min(enumerate(x if x is not None else float('inf') for x in l), key=lambda i: i[1])
enumerate()
片段生成一个像这样的可迭代对象:
0 2.0
1 inf
2 3.0
3 1.0
4 inf
5 2.0
6 inf
7 5.0
然后调用 min()
并使用 enumerate()
return 和 lambda
检查 i[1]
索引中的值(例如 2.0, inf, ..., 5.0
).因此,最终的元组是 returned,仅使用一个生成器从原始列表到 "filter and replace" NoneType
索引进行一次迭代。
您可以定义一个转换函数并将其与 min
:
lst = [2., None, 3., 1., None, 2., None, 5.]
def converter(x):
return x[1] if x[1] is not None else float('inf')
res = min(enumerate(lst), key=converter)[::-1]
(1.0, 3)
如果您喜欢使用第 3 方库,NumPy 中的等价物:
arr = np.array(lst).astype(float)
arr[np.isnan(arr)] = np.inf
res = arr.min(), arr.argmin()
或者,更有效地,您可以使用 np.nanargmin
:
arg = np.nanargmin(arr)
minval = arr[arg]
res = minval, arg
为什么结果应该是(1., 3),在1之后,2在后面
l = [2., None, 3., 1., None, 2., None, 5.]
bar = map(float, [e for e in l if isinstance(e, float)])
print (min(float(i) for i in bar))
min((v,i) for i,v in enumerate(l) if v is not None)
(1.0, 3) # (value, index)
您可以避免像这样使用 key
:
>>> import operator as op
>>> import itertools as it
>>> min(it.filterfalse(op.methodcaller('__contains__', None), zip(l, it.count())))
(1.0, 3)
最复杂的是在列表中替换,我认为:
import numpy as np
l = [2., None, 3., 1., None, 2., None, 5.]
#### function to replace in a list
def replaced(sequence, old, new):
return (new if x == old else x for x in sequence)
l=list(replaced(l,None,np.nan))
#### numpy specific function
position = np.nanargmin(l)
value = l[position]
print(position, value)
虽然我更喜欢接受的答案。 您可以在其中使用 NoneType 的演示代码:
lst = [2., None, 3., 1., None, 2., None, 5.]
def converter(x):
NoneType = type(None)
return x[1] if not isinstance(x[1], NoneType) else float('inf')
res = min(enumerate(lst), key=converter)[::-1]
print(res)
给予
(1.0, 3)