python recipe:列表项最接近等于value

时间:2016-07-06 20:20:28

标签: python

考虑像[0,3,7,10,12,15,19,21]这样的列表,我想得到最接近任何值的最接近的最小数字,所以如果我通过4,我会得到3,如果我通过{ {1}},我会得到18等等。

8 个答案:

答案 0 :(得分:3)

您可以使用bisect并不太难。它用于这样的二进制搜索。这确实假定了一个排序列表。

from bisect import bisect_right

def find_le(a, x):
    'Find rightmost value less than or equal to x'
    i = bisect_right(a, x)
    if i:
        return a[i-1]
    raise ValueError

mylist = [0,3,7,10,12,15,19,21]
print find_le(mylist,4)
print find_le(mylist,-1)
print find_le(mylist,29)
print find_le(mylist,12)

运行互动:

>>> print find_le(mylist,4)
3
>>> print find_le(mylist,-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in find_le
ValueError
>>> print find_le(mylist,29)
21
>>> print find_le(mylist,12)
12

答案 1 :(得分:0)

这里有几个选择。

最简单的是迭代数组并在a)你到达数组末尾时停止或b)当前位置的值大于你要查找的值。然后只需返回找到的最后一个值。 (需要考虑的一个优势:如果请求的数量小于数组的所有值,会发生什么?)

此解决方案假定数组已订购。如果没有,它将无法工作。

答案 2 :(得分:0)

如果您的列表很小,那么迭代它是最好的选择。你可以避免一些开销,加上过度设计这项任务毫无意义。如果您希望您的代码更“正确”,或者您希望在较大的输入上进行良好的扩展,我建议使用二进制搜索方法。当然,这是假设您的输入保证被排序。如果未排序,除了在跟踪delta之前迭代值,您别无选择。以下是二元搜索策略的相对高级别的解释:

  1. 进行二元搜索
  2. 如果等于您要搜索的值,请返回上一个索引处的值。
  3. 如果小于该值,则返回该索引。
  4. 如果大于该值,则返回上一个索引。
  5. 通过一些示例来向自己证明这将起作用可能会有所帮助。

答案 3 :(得分:0)

您可以使用yieldnext()来避免迭代整个列表

在线演示 - https://repl.it/C9YJ/1

values = [0,3,7,10,12,15,19,21]

def get_closest(value, items):

    previews_item = None
    for item in items:
        if item >= value:
            yield previews_item

        previews_item = max(item, previews_item) if previews_item else item

    yield None


print next(get_closest(4, values))
# 3

print next(get_closest(18, values))
# 15

答案 4 :(得分:0)

真的很乱,可能是效率低下的解决方案,但它有效

test=[0,3,7,10,12,15,19,21]
value=25
nearest=[]
for i in test:
    if i == value:
        nearest.append(test[(test.index(i))])
        break
    if i>value:
        nearest.append(test[(test.index(i))-1])
        break
if len(nearest) == 0:
    nearest.append(test[-1])

print nearest[0]

答案 5 :(得分:0)

x = [0,3,7,10,12,15,19,21]
val = 18

x.sort()
close =  [abs(_ - val) for _ in x]
ans = (x[close.index(min(close))])
if ans > val:
    ans = (x[close.index(min(close)) -1])
print (ans)

评论:

(1。)我们不能假设原件是预先分类的,因为它没有这样指定。因此,我做了一个就地排序。如果需要保留列表项的顺序,则复制列表然后排序。

(2。)有一些使用bisect模块和使用迭代器的优秀帖子。我想通过演示列表推导以及使用抛弃变量(下划线)来展示另一种方式。

(3。)如果列表很长,你应该使用bisect。如果列表很短(指定不超过几百),请不要过度设计代码;线性搜索很好。请记住,在软件中,你总是在兼顾,时间与空间,可读性,可维护性等等。

答案 6 :(得分:0)

使用bisect。
一个问题:一旦检查号码小于列表中的第一个元素

,代码将给出最后一个元素
import bisect
lst = [0, 3, 7, 10, 12, 15, 19, 21]
lst[bisect.bisect_left(lst,-1) - 1]

答案 7 :(得分:-2)

好吧, $('form').on('submit',function(e){ e.preventDefault() // TODO console.log('Form is submitted to the server'); }); $("#Color").change(function () { $(this).find("option:selected").each(function(){ var val = $(this).attr("value"); var box = $(".box"); if(val=="redd"){ box.not("." + val).hide().find("input").removeAttr('required'); $("." + val).show().find("input").prop("required", true); } else if(val=="greenn"){ box.not("." + val).hide().find("input").removeAttr('required'); $("." + val).show().find("input").prop("required", true); } else{ $(".box").hide(); } }); }).change(); 是列表,a是值:

b

更有效的方式?可能不是吗?