简体   繁体   English

最小最大python v3实现

[英]Min-max python v3 implementation

I'm currently trying to code an equivalent for the built-in min-max function in python, and my code return a pretty weird exception which I don't understand at all: 我目前正在尝试为python中的内置min-max函数编写等效代码,并且我的代码返回一个非常奇怪的异常,我根本无法理解:

TypeError: 'generator' object is not subscriptable, min, 7, , 9

when i try it with: 当我尝试使用:

min(abs(i) for i in range(-10, 10))

Here is my code: 这是我的代码:

def min(*args, **kwargs):
key = kwargs.get("key", None)
argv=0
for i in args:
    argv+=1
    if argv == 1 and (type(args) is list or type(args) is tuple or type(args) is str):
        min=args[0][0]
        for i in args[0]:
            if key != None:
                if key(i) < key(min):
                    min = i
            else:
                if i < min:
                    min = i
        return min
    else:
        min=args[0]
        for i in args:
            if key != None:
                if key(i) < key(min):
                    min = i
            else:
                if i < min:
                    min = i
        return min

According to the documentation, i should be able to iterate over a generator... 根据文档,我应该能够迭代一个生成器...

The issue you are having is due to the fact that min has two function signatures. 您遇到的问题是因为min具有两个函数签名。 From its docstring: 从其文档字符串:

min(...)
    min(iterable[, key=func]) -> value
    min(a, b, c, ...[, key=func]) -> value

So, it will accept either a single positional argument (an iterable, who's values you need to compare) or several positional arguments which are the values themselves. 因此,它将接受一个位置参数(一个可迭代的值,您需要比较谁的值)或几个位置参数(它们是值本身)。 I think you need to test which mode you're in at the start of your function. 我认为您需要在功能开始时测试您所处的模式。 It is pretty easy to turn the one argument version into the multiple argument version simply by doing args = args[0] . 只需执行args = args[0]即可将一个参数版本转换为多参数版本,这非常容易。

Here's my attempt to implement the function. 这是我实现该功能的尝试。 key is a keyword-only argument, since it appears after *args . key是仅关键字的参数,因为它出现在*args

def min(*args, key=None):    # args is a tuple of the positional arguments initially
    if len(args) == 1:       # if there's just one, assume it's an iterable of values
        args = args[0]       # replace args with the iterable

    it = iter(args)          # get an iterator

    try:
        min_val = next(it)   # take the first value from the iterator
    except StopIteration:
        raise ValueError("min() called with no values")

    if key is None:       # separate loops for key=None and otherwise, for efficiency
        for val in it:    # loop on the iterator, which has already yielded one value
            if val < min_val
                min_val = val
    else:
        min_keyval = key(min_val)    # initialize the minimum keyval
        for val in it:
            keyval = key(val)
            if keyval < min_keyval:  # compare keyvals, rather than regular values
                min_val = val
                min_keyval = keyval

    return min_val

Here's some testing: 这是一些测试:

>>> min([4, 5, 3, 2])
2
>>> min([1, 4, 5, 3, 2])
1
>>> min(4, 5, 3, 2)
2
>>> min(4, 5, 3, 2, 1)
1
>>> min(4, 5, 3, 2, key=lambda x: -x)
5
>>> min(4, -5, 3, -2, key=abs)
-2
>>> min(abs(i) for i in range(-10, 10))
0

Here is my implementation: 这是我的实现:

def max(*args, **kwargs):
    key = kwargs.get("key", lambda x: x)
    if len(args) == 1:
        args = args[0]
    maxi = None
    for i in args:
        if maxi == None or key(i) > key(maxi):
            maxi = i
    return maxi

def min(*args, **kwargs):
    key = kwargs.get("key", lambda x: x)
    if len(args) == 1:
        args = args[0]
    mini = None
    for i in args:
        if mini == None or key(i) < key(mini):
            mini = i
    return mini

A little bit more concise than preview post. 比预览帖子更简洁。

Functions in question have a lot in common. 有问题的功能有很多共同点。 In fact, the only difference is comparison ( < vs > ). 实际上,唯一的区别是比较( < vs > )。 In the light of this fact we can implement generic function for finding and element, which will use comparison function passed as an argument. 根据这一事实,我们可以实现用于查找和元素的泛型函数,它将使用作为参数传递的比较函数。 The min and max example might look as follows: 最小和最大示例如下所示:

def lessThan(val1, val2):
  return val1 < val2

def greaterThan(val1, val2):
  return val1 > val2


def find(cmp, *args, **kwargs):
  if len(args) < 1:
    return None

  key = kwargs.get("key", lambda x: x)
  arguments = list(args[0]) if len(args) == 1 else args
  result = arguments[0]

  for val in arguments:
    if cmp(key(val), key(result)):
      result = val

  return result


min = lambda *args, **kwargs: find(lessThan, *args, **kwargs)
max = lambda *args, **kwargs: find(greaterThan, *args, **kwargs)

Some tests: 一些测试:

>>> min(3, 2)
2
>>> max(3, 2)
3
>>> max([1, 2, 0, 3, 4])
4
>>> min("hello")
'e'
>>> max(2.2, 5.6, 5.9, key=int)
5.6
>>> min([[1, 2], [3, 4], [9, 0]], key=lambda x: x[1])
[9, 0]
>>> min((9,))
9
>>> max(range(6))
5
>>> min(abs(i) for i in range(-10, 10))
0
>>> max([1, 2, 3], [5, 6], [7], [0, 0, 0, 1])
[7]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM