ソートされたcsvから次のリストを作成しました
list1 = sorted(csv1, key=operator.itemgetter(1))
最初にフィールド1の値で、次にフィールド2の値で、2つの基準でリストを実際にソートしたいと思います。これを行う方法を教えてください。
__lt__()
クラスのメソッドを定義するか、そうするクラスから継承する」です。それはそれをはるかに良い正規化するでしょう。
ソートされたcsvから次のリストを作成しました
list1 = sorted(csv1, key=operator.itemgetter(1))
最初にフィールド1の値で、次にフィールド2の値で、2つの基準でリストを実際にソートしたいと思います。これを行う方法を教えてください。
__lt__()
クラスのメソッドを定義するか、そうするクラスから継承する」です。それはそれをはるかに良い正規化するでしょう。
回答:
このような:
import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))
operator
インポートする必要があるモジュールです。
ラムダ関数を使用するときに何もインポートする必要はありません。
次の例でlist
は、最初の要素、2番目の要素の順に並べ替えます。
sorted(list, key=lambda x: (x[0], -x[1]))
-
in は何の-x[1]
略ですか?
Pythonは安定したソートを備えているため、パフォーマンスが問題にならない限り、フィールド2でソートしてからフィールド1で再度ソートするのが最も簡単な方法です。
それはあなたにあなたが望む結果を与えるでしょう、唯一のキャッチはそれが大きなリストであるなら(またはあなたがそれを頻繁にソートしたいなら)sortを2回呼び出すことは許容できないオーバーヘッドになるかもしれないということです。
list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))
このようにすることで、一部の列を逆に並べ替えたい場合の処理も簡単になり、必要に応じて 'reverse = True'パラメータを含めるだけです。
それ以外の場合は、itemgetterに複数のパラメーターを渡すか、手動でタプルを作成できます。それはおそらくより高速になりますが、一部の列を逆ソートしたい場合、一般化がうまくいかないという問題があります(数値列は否定することによって逆にすることはできますが、ソートが安定しなくなります)。
したがって、列を逆に並べ替える必要がない場合は、itemgetterに複数の引数を使用します。可能であれば、列が数値でないか、並べ替えを安定した状態に保ち、複数の連続した並べ替えを行います。
編集:これが元の質問にどのように答えるかを理解するのに問題があるコメンターのために、これはソートの安定した性質がどのように各キーで個別のソートを実行し、複数の基準でソートされたデータになるかを正確に示す例です:
DATA = [
('Jones', 'Jane', 58),
('Smith', 'Anne', 30),
('Jones', 'Fred', 30),
('Smith', 'John', 60),
('Smith', 'Fred', 30),
('Jones', 'Anne', 30),
('Smith', 'Jane', 58),
('Smith', 'Twin2', 3),
('Jones', 'John', 60),
('Smith', 'Twin1', 3),
('Jones', 'Twin1', 3),
('Jones', 'Twin2', 3)
]
# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
print("{:10s} {:10s} {}".format(*d))
これは実行可能な例ですが、実行している人を救うための出力は次のとおりです。
Initial data in random order
Jones Jane 58
Smith Anne 30
Jones Fred 30
Smith John 60
Smith Fred 30
Jones Anne 30
Smith Jane 58
Smith Twin2 3
Jones John 60
Smith Twin1 3
Jones Twin1 3
Jones Twin2 3
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Jones Jane 58
Smith Jane 58
Smith John 60
Jones John 60
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith John 60
Jones John 60
Jones Jane 58
Smith Jane 58
Smith Anne 30
Jones Anne 30
Jones Fred 30
Smith Fred 30
Smith Twin1 3
Jones Twin1 3
Smith Twin2 3
Jones Twin2 3
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
Jones John 60
Jones Jane 58
Jones Anne 30
Jones Fred 30
Jones Twin1 3
Jones Twin2 3
Smith John 60
Smith Jane 58
Smith Anne 30
Smith Fred 30
Smith Twin1 3
Smith Twin2 3
特に、2番目のステップでreverse=True
パラメーターが最初の名前を順番に保持する方法に注意してください。一方、単に並べ替えてからリストを逆にすると、3番目の並べ替えキーの目的の順序が失われます。
list1 = sorted(csv1, key=lambda x: (x[1], x[2]) )
tuple()
2つの引数を受け取ることができるとは思いません(または、で数えると3つself
)
return
ステートメントは、return tuple((x[1], x[2]))
または単にする必要がありますreturn x[1], x[2]
。 別の方向でのソートをお探しの場合は、@ jaapの回答を参照してください
tuple(x[1:3])
、タプルディスプレイリストだけでなく、何らかの理由でタプルコンストラクタを使用する場合x[1], x[2]
。またはkeyfunc = operator.itemgetter(1, 2)
、関数を自分で作成しないでください。
employees.sort(key = lambda x:x[1])
employees.sort(key = lambda x:x[0])
python sortが適切で安定しているため、.sortをlambdaで2回使用することもできます。これは最初に、2番目の要素x [1]に従ってリストをソートします。次に、最初の要素x [0](最高優先度)をソートします。
employees[0] = Employee's Name
employees[1] = Employee's Salary
これは、以下を実行することと同等です。employees.sort(key = lambda x:(x [0]、x [1]))