import itertools as IT
first = {
('monkey',1): 130.0,
('dog',2): 123.0,
('cat', 3): 130.0,
('cat', 4): 130.0,
('mouse', 6): 100.0
}
counter = 0
ordered = sorted(first, key = lambda k: (first[k], k[1], k[0]))
second = {}
for key, group in IT.groupby(ordered, first.__getitem__):
# group = list(group)
# print(key, group)
# (100.0, [('mouse', 6)])
# (123.0, [('dog', 2)])
# (130.0, [('monkey', 1), ('cat', 3), ('cat', 4)])
previous = None
for name, num in group:
if name != previous:
counter += 1
second[num] = counter
previous = name
print(second)
収量
{1: 3, 2: 2, 3: 4, 4: 4, 6: 1}
説明:
最初のステップは、関連する値に従っての(name, num)
キーを並べ替えることです。first
ただし、同点の場合num
はを使用します。それでも同点の場合は、name
を使用して同点を解除します。
In [96]: ordered = sorted(first, key = lambda k: (first[k], k[1], k[0]))
In [97]: ordered
Out[97]: [('mouse', 6), ('dog', 2), ('monkey', 1), ('cat', 3), ('cat', 4)]
次に、値が同じordered
場合は特別なルールがあるため、アイテムをグループ化する必要があります。first[k]
グループ化は、itertools.groupbyを使用して実現できます。
In [99]: for key, group in IT.groupby(ordered, first.__getitem__):
....: print(key, list(group))
....:
....:
(100.0, [('mouse', 6)])
(123.0, [('dog', 2)])
(130.0, [('monkey', 1), ('cat', 3), ('cat', 4)])
itertools.groupby
キーの値に応じてアイテムordered
を束にまとめていますfirst.__getitem__(item)
。例えば、
In [100]: first.__getitem__(('monkey', 1))
Out[100]: 130.0
In [101]: first.__getitem__(('cat', 3))
Out[101]: 130.0
first.__getitem__(item)
ただの凝った書き方first[item]
です。私が使用する理由first.__getitem__
はitertools.groupby
、2番目の引数に関数を期待しfirst.__getitem__
、法案に適合する関数であるためです。
最後に、各グループを繰り返し処理します。基本的に、これを実行したいと思います。
for name, num in group:
counter += 1
second[num] = counter
ただし、名前が等しい場合は、カウンターを進めたくありません。したがって、名前が等しいかどうかを確認するには、以前の名前を保存すると便利です。
previous = None
for name, num in group:
if name != previous:
counter += 1
...
previous = name
警告:rkd91のコードと私のコードは異なる答えを生成することに注意してください
first = {
('monkey',1): 130.0,
('dog',2): 123.0,
('cat', 3): 129.0,
('cat', 4): 130.0,
('mouse', 6): 100.0
}
おそらく仕様の解釈が異なるためです。どちらが目的の出力を生成するかは、あなたに任せます。
@rdk91のコードは
{1: 4, 2: 2, 3: 5, 4: 3, 6: 1}
私のコードは
{1: 4, 2: 2, 3: 3, 4: 5, 6: 1}