web-dev-qa-db-ja.com

空のリスト用の安全なmax()関数

評価する、

max_val = max(a)

エラーが発生します

ValueError: max() arg is an empty sequence

tryexceptキャッチ以外に、このエラーから保護するより良い方法はありますか?

a = []
try:
    max_val = max(a)
except ValueError:
    max_val = default 
34

Python 3.4+では、 defaultキーワード引数 :を使用できます。

>>> max([], default=99)
99

下位バージョンでは、orを使用できます:

>>> max([] or [99])
99

注:2番目のアプローチは、すべての反復可能オブジェクトに対して機能するわけではありません。特に、真理値のみを考慮したイテレータに対して。

>>> max(iter([]) or 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: max() arg is an empty sequence
47
falsetru

Python 3.4より古いバージョンでは、itertools.chain()を使用して、空のシーケンスに別の値を追加できます。これにより、空の反復可能オブジェクトが処理されますが、余分な値が常に含まれているため、default引数を指定するのと同じです。

>>> from itertools import chain
>>> max(chain([42], []))
42

ただし、Python 3.4では、シーケンスが空でない場合、デフォルトは無視されます。

>>> max([3], default=42)
3
8
Duncan

別の解決策は、三項演算子を使用することです。

nums = []
max_val = max(nums) if nums else 0

または

max val = max(iter(nums) if nums else [0])
1
Kurohige

上記のすべてのコメントを考慮すると、次のようなラッパーになります。

def max_safe(*args, **kwargs):
    """
    Returns max element of an iterable.

    Adds a `default` keyword for any version of python that do not support it
    """
    if sys.version_info < (3, 4):  # `default` supported since 3.4
        if len(args) == 1:
            arg = args[0]
            if 'default' in kwargs:
                default = kwargs.pop('default')
                if not arg:
                    return default

                # https://stackoverflow.com/questions/36157995#comment59954203_36158079
                arg = list(arg)
                if not arg:
                    return default

                # if the `arg` was an iterator, it's exhausted already
                # so use a new list instead
                return max(arg, **kwargs)

    return max(*args, **kwargs)
0
tsionyx

空のシーケンスの最大値は、シーケンスの要素が持つあらゆるタイプの無限に小さなものでなければなりません。残念なことに、(1)空のシーケンスでは、要素がどのタイプを持っているのかわからず、(2)Pythonで最も負の整数のようなものはありません。

したがって、この場合に賢明なことをしたい場合は、max outを支援する必要があります。 Pythonの最近のバージョンでは、defaultmax引数があります(これは誤解を招く名前のように見えますが、気にしません)。空のシーケンスを渡します。古いバージョンでは、渡すシーケンスが空でないことを確認する必要があります。たとえば、使用したい値を含むシングルトンシーケンスでoringすることによってその場合。

[Yaakov Belchが「無限に大きい」と書いたコメントで親切に指摘していたので、投稿してからずっと編集しました。

0