Python Language
並べ替え、最小値と最大値
サーチ…
いくつかの値の最小値または最大値の取得
min(7,2,1,5)
# Output: 1
max(7,2,1,5)
# Output: 7
key引数の使用
シーケンスのシーケンスの最小/最大を見つけることは可能です:
list_of_tuples = [(0, 10), (1, 15), (2, 8)]
min(list_of_tuples)
# Output: (0, 10)
しかし、各シーケンスの特定の要素でソートする場合は、 key
-argumentを使用しkey
。
min(list_of_tuples, key=lambda x: x[0]) # Sorting by first element
# Output: (0, 10)
min(list_of_tuples, key=lambda x: x[1]) # Sorting by second element
# Output: (2, 8)
sorted(list_of_tuples, key=lambda x: x[0]) # Sorting by first element (increasing)
# Output: [(0, 10), (1, 15), (2, 8)]
sorted(list_of_tuples, key=lambda x: x[1]) # Sorting by first element
# Output: [(2, 8), (0, 10), (1, 15)]
import operator
# The operator module contains efficient alternatives to the lambda function
max(list_of_tuples, key=operator.itemgetter(0)) # Sorting by first element
# Output: (2, 8)
max(list_of_tuples, key=operator.itemgetter(1)) # Sorting by second element
# Output: (1, 15)
sorted(list_of_tuples, key=operator.itemgetter(0), reverse=True) # Reversed (decreasing)
# Output: [(2, 8), (1, 15), (0, 10)]
sorted(list_of_tuples, key=operator.itemgetter(1), reverse=True) # Reversed(decreasing)
# Output: [(1, 15), (0, 10), (2, 8)]
デフォルトの引数max、min
空のシーケンスをmax
またはmin
渡すことはできません:
min([])
ValueError:min()argは空のシーケンスです
しかし、Python 3では、例外を発生させる代わりに、シーケンスが空の場合に返される値をキーワード引数default
渡すことができます。
max([], default=42)
# Output: 42
max([], default=0)
# Output: 0
特別な場合:辞書
最小値または最大値を取得するかsorted
を使用するかは、オブジェクトの反復によって異なります。 dict
の場合、反復はキーの上だけです:
adict = {'a': 3, 'b': 5, 'c': 1}
min(adict)
# Output: 'a'
max(adict)
# Output: 'c'
sorted(adict)
# Output: ['a', 'b', 'c']
辞書構造を保持するには、 .items()
を繰り返し処理する必要があり.items()
。
min(adict.items())
# Output: ('a', 3)
max(adict.items())
# Output: ('c', 1)
sorted(adict.items())
# Output: [('a', 3), ('b', 5), ('c', 1)]
sorted
場合は、 OrderedDict
を作成して、 dict
ような構造を持ちながらソートを維持できます。
from collections import OrderedDict
OrderedDict(sorted(adict.items()))
# Output: OrderedDict([('a', 3), ('b', 5), ('c', 1)])
res = OrderedDict(sorted(adict.items()))
res['a']
# Output: 3
値で
やはりこれはkey
引数を使って可能です:
min(adict.items(), key=lambda x: x[1])
# Output: ('c', 1)
max(adict.items(), key=operator.itemgetter(1))
# Output: ('b', 5)
sorted(adict.items(), key=operator.itemgetter(1), reverse=True)
# Output: [('b', 5), ('a', 3), ('c', 1)]
並べ替えられたシーケンスの取得
1つのシーケンスの使用:
sorted((7, 2, 1, 5)) # tuple
# Output: [1, 2, 5, 7]
sorted(['c', 'A', 'b']) # list
# Output: ['A', 'b', 'c']
sorted({11, 8, 1}) # set
# Output: [1, 8, 11]
sorted({'11': 5, '3': 2, '10': 15}) # dict
# Output: ['10', '11', '3'] # only iterates over the keys
sorted('bdca') # string
# Output: ['a','b','c','d']
結果は常に新しいlist
です。元のデータは変更されません。
シーケンスの最小値と最大値
シーケンスの最小値(iterable)を取得することは、 sorted
シーケンスの最初の要素にアクセスすることと同じです。
min([2, 7, 5])
# Output: 2
sorted([2, 7, 5])[0]
# Output: 2
sorted
は順序を保持し、 max
は最初に出会った値を返すため、最大値は少し複雑です。重複がない場合、最大値はソートされたリターンの最後の要素と同じです。
max([2, 7, 5])
# Output: 7
sorted([2, 7, 5])[-1]
# Output: 7
しかし、最大値を持つと評価される複数の要素がある場合はそうではありません。
class MyClass(object):
def __init__(self, value, name):
self.value = value
self.name = name
def __lt__(self, other):
return self.value < other.value
def __repr__(self):
return str(self.name)
sorted([MyClass(4, 'first'), MyClass(1, 'second'), MyClass(4, 'third')])
# Output: [second, first, third]
max([MyClass(4, 'first'), MyClass(1, 'second'), MyClass(4, 'third')])
# Output: first
<
または>
演算をサポートする要素を含む反復可能なものはすべて許可されます。
カスタムクラスを注文可能にする
min
、 max
、およびsorted
すべてオブジェクトを注文可能にする必要があります。適切に注文可能であるためには、クラスが6つのメソッドをすべて定義する必要がある__lt__
、 __gt__
、 __ge__
、 __le__
、 __ne__
と__eq__
:
class IntegerContainer(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.value)
def __lt__(self, other):
print('{!r} - Test less than {!r}'.format(self, other))
return self.value < other.value
def __le__(self, other):
print('{!r} - Test less than or equal to {!r}'.format(self, other))
return self.value <= other.value
def __gt__(self, other):
print('{!r} - Test greater than {!r}'.format(self, other))
return self.value > other.value
def __ge__(self, other):
print('{!r} - Test greater than or equal to {!r}'.format(self, other))
return self.value >= other.value
def __eq__(self, other):
print('{!r} - Test equal to {!r}'.format(self, other))
return self.value == other.value
def __ne__(self, other):
print('{!r} - Test not equal to {!r}'.format(self, other))
return self.value != other.value
これらのメソッドをすべて実装する必要はないようですが、それらのメソッドを省略するとコードがバグになりやすくなります 。
例:
alist = [IntegerContainer(5), IntegerContainer(3),
IntegerContainer(10), IntegerContainer(7)
]
res = max(alist)
# Out: IntegerContainer(3) - Test greater than IntegerContainer(5)
# IntegerContainer(10) - Test greater than IntegerContainer(5)
# IntegerContainer(7) - Test greater than IntegerContainer(10)
print(res)
# Out: IntegerContainer(10)
res = min(alist)
# Out: IntegerContainer(3) - Test less than IntegerContainer(5)
# IntegerContainer(10) - Test less than IntegerContainer(3)
# IntegerContainer(7) - Test less than IntegerContainer(3)
print(res)
# Out: IntegerContainer(3)
res = sorted(alist)
# Out: IntegerContainer(3) - Test less than IntegerContainer(5)
# IntegerContainer(10) - Test less than IntegerContainer(3)
# IntegerContainer(10) - Test less than IntegerContainer(5)
# IntegerContainer(7) - Test less than IntegerContainer(5)
# IntegerContainer(7) - Test less than IntegerContainer(10)
print(res)
# Out: [IntegerContainer(3), IntegerContainer(5), IntegerContainer(7), IntegerContainer(10)]
reverse=True
sorted
ても__lt__
使用され__lt__
:
res = sorted(alist, reverse=True)
# Out: IntegerContainer(10) - Test less than IntegerContainer(7)
# IntegerContainer(3) - Test less than IntegerContainer(10)
# IntegerContainer(3) - Test less than IntegerContainer(10)
# IntegerContainer(3) - Test less than IntegerContainer(7)
# IntegerContainer(5) - Test less than IntegerContainer(7)
# IntegerContainer(5) - Test less than IntegerContainer(3)
print(res)
# Out: [IntegerContainer(10), IntegerContainer(7), IntegerContainer(5), IntegerContainer(3)]
しかしsorted
は、デフォルトが実装されていない場合は代わりに__gt__
を使用できます。
del IntegerContainer.__lt__ # The IntegerContainer no longer implements "less than"
res = min(alist)
# Out: IntegerContainer(5) - Test greater than IntegerContainer(3)
# IntegerContainer(3) - Test greater than IntegerContainer(10)
# IntegerContainer(3) - Test greater than IntegerContainer(7)
print(res)
# Out: IntegerContainer(3)
__lt__
も__gt__
も実装されていなければ、ソートメソッドはTypeError
させます:
del IntegerContainer.__gt__ # The IntegerContainer no longer implements "greater then"
res = min(alist)
TypeError:順序付け不可能な型:IntegerContainer()<IntegerContainer()
functools.total_ordering
デコレータを使用すると、これらの豊富な比較メソッドを簡単に作成できます。あなたとあなたのクラスを飾る場合total_ordering
、あなたが実装する必要が__eq__
、 __ne__
との唯一の__lt__
、 __le__
、 __ge__
または__gt__
、そしてデコレータは休息に入力されます:
import functools
@functools.total_ordering
class IntegerContainer(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.value)
def __lt__(self, other):
print('{!r} - Test less than {!r}'.format(self, other))
return self.value < other.value
def __eq__(self, other):
print('{!r} - Test equal to {!r}'.format(self, other))
return self.value == other.value
def __ne__(self, other):
print('{!r} - Test not equal to {!r}'.format(self, other))
return self.value != other.value
IntegerContainer(5) > IntegerContainer(6)
# Output: IntegerContainer(5) - Test less than IntegerContainer(6)
# Returns: False
IntegerContainer(6) > IntegerContainer(5)
# Output: IntegerContainer(6) - Test less than IntegerContainer(5)
# Output: IntegerContainer(6) - Test equal to IntegerContainer(5)
# Returns True
どのように>
( より大きい )がより小さいメソッドを呼び出すか、場合によっては__eq__
メソッドを__eq__
方法に__eq__
。これは、速度が非常に重要な場合は、それぞれの豊富な比較方法を自分で実装する必要があることを意味します。
iterableからN個の最大アイテムまたはN個の最小アイテムを抽出する
iterableの最大値または最小値のいくつかの数(複数)を見つけるには、 heapq
モジュールのnlargest
とnsmallest
を使用します。
import heapq
# get 5 largest items from the range
heapq.nlargest(5, range(10))
# Output: [9, 8, 7, 6, 5]
heapq.nsmallest(5, range(10))
# Output: [0, 1, 2, 3, 4]
これは、イテラブル全体をソートし、最後または最初からスライスするよりはるかに効率的です。内部的には、これらの関数はバイナリヒープ 優先順位キューのデータ構造を使用します。これは、このユースケースでは非常に効率的です。
min
、 max
、 sorted
と同様に、これらの関数はオプションのkey
キーワード引数を受け取ります。これは、与えられた要素に対してソートキーを返す関数でなければなりません。
ファイルから1000行分を抽出するプログラムを以下に示します。
import heapq
with open(filename) as f:
longest_lines = heapq.nlargest(1000, f, key=len)
ここでファイルを開き、ファイルハンドルf
をnlargest
ます。ファイルを反復すると、ファイルの各行が別々の文字列として生成されます。 nlargest
は各要素( nlargest
)を渡して関数len
に渡し、ソートキーを決定します。 len
は文字列で与えられ、行の長さを文字数で返します。
これは今までの1000行のリストのためのストレージしか必要としません。
longest_lines = sorted(f, key=len)[1000:]
ファイル全体をメモリに保持する必要があります 。