このような文字列のリストがあります。
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
次の出力を得るためにYからの値を使用してXをソートする最短の方法は何ですか?
["a", "d", "h", "b", "c", "e", "i", "f", "g"]
同じ「キー」を持つ要素の順序は関係ありません。私はfor
構造の使用に頼ることができますが、もっと短い方法があるかどうか私は興味があります。助言がありますか?
最短コード
[x for _,x in sorted(Zip(Y,X))]
例:
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
Z = [x for _,x in sorted(Zip(Y,X))]
print(Z) # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]
一般的に言えば
[x for _, x in sorted(Zip(Y,X), key=lambda pair: pair[0])]
説明:
Zip
2つのlist
s。sorted()
を使用して、list
に基づいて新しいソート済みのZip
を作成します。list
から各ペアの最初の要素を抽出します。一般的なkey
関数と同様にsorted
パラメータを設定\使用する方法についてのさらなる情報は、 this をご覧ください。
2つのリストをまとめて圧縮し、並べ替えてから、必要な部分を取り出します。
>>> yx = Zip(Y, X)
>>> yx
[(0, 'a'), (1, 'b'), (1, 'c'), (0, 'd'), (1, 'e'), (2, 'f'), (2, 'g'), (0, 'h'), (1, 'i')]
>>> yx.sort()
>>> yx
[(0, 'a'), (0, 'd'), (0, 'h'), (1, 'b'), (1, 'c'), (1, 'e'), (1, 'i'), (2, 'f'), (2, 'g')]
>>> x_sorted = [x for y, x in yx]
>>> x_sorted
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']
得るためにこれらを一緒に組み合わせてください:
[x for y, x in sorted(Zip(Y, X))]
また、厄介な配列を使用しても構わない場合(または実際には既に厄介な配列を処理している場合...)、これはもう1つの良い解決策です。
people = ['Jim', 'Pam', 'Micheal', 'Dwight']
ages = [27, 25, 4, 9]
import numpy
people = numpy.array(people)
ages = numpy.array(ages)
inds = ages.argsort()
sortedPeople = people[inds]
私はここでそれを見つけました: http://scienceoss.com/sort-one-list-by-another-list/
私にとって最も明白な解決策はkey
キーワードargを使うことです。
>>> X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
>>> Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
>>> keydict = dict(Zip(X, Y))
>>> X.sort(key=keydict.get)
>>> X
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']
次のことを行う場合は、これをワンライナーにすることができます。
>>> X.sort(key=dict(Zip(X, Y)).get)
ソートされたインデックスのリストが好きです。こうすることで、ソースリストと同じ順序で任意のリストを並べ替えることができます。ソートされたインデックスのリストを取得したら、単純なリスト内包表記でうまくいきます。
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
sorted_y_idx_list = sorted(range(len(Y)),key=lambda x:Y[x])
Xs = [X[i] for i in sorted_y_idx_list ]
print( "Xs:", Xs )
# prints: Xs: ["a", "d", "h", "b", "c", "e", "i", "f", "g"]
ソートされたインデックスリストは、numpy argsort()を使って取得することもできます。
いくつかの答えを組み合わせた、もう1つの選択肢。
Zip(*sorted(Zip(Y,X)))[1]
Python3のために働くために:
list(Zip(*sorted(Zip(B,A))))[1]
more_itertools
には、反復可能オブジェクトを並列にソートするためのツールがあります。
from more_itertools import sort_together
sort_together([Y, X])[1]
# ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')
Zip、2列目でソート、1列目を返します。
Zip(*sorted(Zip(X,Y), key=operator.itemgetter(1)))[0]
実際にここに来たのは、値が一致したリストでリストをソートすることです。
list_a = ['foo', 'bar', 'baz']
list_b = ['baz', 'bar', 'foo']
sorted(list_b, key=lambda x: list_a.index(x))
# ['foo', 'bar', 'baz']
素早いワンライナー。
list_a = [5,4,3,2,1]
list_b = [1,1.5,1.75,2,3,3.5,3.75,4,5]
リストaをリストbに一致させるとします。
orderedList = sorted(list_a, key=lambda x: list_b.index(x))
小さいリストを大きい値に並べ替える必要がある場合に便利です。大きい方のリストに小さい方のリスト内のすべての値が含まれていると仮定すれば、実行できます。
@ Whatangの答えにヒントを得て、もっと一般的な関数を作成しました。これは、2つ以上のリストを別のリストに基づいてソートするものです。
def parallel_sort(*lists):
"""
Sorts the given lists, based on the first one.
:param lists: lists to be sorted
:return: a Tuple containing the sorted lists
"""
# Create the initially empty lists to later store the sorted items
sorted_lists = Tuple([] for _ in range(len(lists)))
# Unpack the lists, sort them, Zip them and iterate over them
for t in sorted(Zip(*lists)):
# list items are now sorted based on the first list
for i, item in enumerate(t): # for each item...
sorted_lists[i].append(item) # ...store it in the appropriate list
return sorted_lists
一次リストをdata
として、他のリストをindex
として使ってpandas Series
を作成し、インデックスでソートするだけです。
import pandas as pd
pd.Series(data=X,index=Y).sort_index().tolist()
出力:
['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']
両方のソートされたリストを入手したい場合は、Whatangsがこれに答えます(python3)。
X = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
Y = [ 0, 1, 1, 0, 1, 2, 2, 0, 1]
Zx, Zy = Zip(*[(x, y) for x, y in sorted(Zip(Y, X))])
print(list(Zx)) # [0, 0, 0, 1, 1, 1, 1, 2, 2]
print(list(Zy)) # ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']
ZxとZyはタプルであることを忘れないでください。私はそれをするよりよい方法があるかどうかも放浪しています。
警告:空のリストで実行するとクラッシュします。
list1 = ['a','b','c','d','e','f','g','h','i']
list2 = [0,1,1,0,1,2,2,0,1]
output=[]
cur_loclist = []
list2
に存在する一意の値を取得する
list_set = set(list2)
list2
でインデックスの場所を見つけるには
list_str = ''.join(str(s) for s in list2)
list2
内のインデックスの位置はcur_loclist
を使用して追跡されます
[0、3、7、1、2、4、8、5、6]
for i in list_set:
cur_loc = list_str.find(str(i))
while cur_loc >= 0:
cur_loclist.append(cur_loc)
cur_loc = list_str.find(str(i),cur_loc+1)
print(cur_loclist)
for i in range(0,len(cur_loclist)):
output.append(list1[cur_loclist[i]])
print(output)