カスタム等値演算子を使用してリストを一意にする最もpythonicな方法は何ですか?
たとえば、 dicts のリストがあり、すべての dicts 、in 、および特定の 1 つに対してL
新しいリストが必要な場合M
d
e
M
x
d[x] != e[x]
これはどのように行うことができますか?
カスタム等値演算子を使用してリストを一意にする最もpythonicな方法は何ですか?
たとえば、 dicts のリストがあり、すべての dicts 、in 、および特定の 1 つに対してL
新しいリストが必要な場合M
d
e
M
x
d[x] != e[x]
これはどのように行うことができますか?
あなたの場合(および同等性がある種のキーの同等性に帰着するすべての場合)、キーが比較したい値である辞書を簡単に作成できます。
L = [{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}, {'key': 'foo', 'v': 44}]
x = 'key'
M = {d[x]:d for d in L}.values()
# In old Python versions: dict((d[x],d for d in L)).values()
結果は決定論的ではないことに注意してください。
[{'key': 'foo', 'v': 44}, {'key': 'bar', 'v': 43}]
と
[{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}]
は有効な結果です。
一般的なケースでは、受け入れられたすべての値を確認するだけです。
def unique(iterable, is_eq):
tmp = []
for el in iterable:
if not any(is_eq(inTmp, el) for inTmp in tmp):
tmp.append(is_eq)
return tmp
これは、比較関数がO(n²)
times ではなく timesと呼ばれることを意味することに注意してくださいn
。
FUD の phihag へのコメントに基づいています。key
関数はハッシュ可能な値を返さなければならないことに注意してください。
def unique(iterable, key=lambda x : x):
seen = set()
res = []
for item in iterable:
k = key(item)
if k not in seen:
res.append(item)
seen.add(k)
return res
from operator import itemgetter
L = [{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}, {'key': 'foo', 'v': 44}]
print unique(L, key=itemgetter('key'))
#[{'key': 'foo', 'v': 42}, {'key': 'bar', 'v': 43}]
辞書理解の使用:
def unique(itrable,key):
return {key(x):x for x in itrable}.values()
>>> unique('abcdbbcdab', lambda x: x)
['a', 'c', 'b', 'd']
>>> unique([10, -20, 20, 30], lambda x: abs(x))
[10, 20, 30]
この種のことがワンライナーを認めているかどうかはわかりませんが、set
クラスがあなたが望むものの鍵であるように思えます。
M = []
uniques = set(d[x] for d in L)
for d in L:
if d[x] in uniques:
uniques.remove(d[x])
M.append(d)
注: phihag の回答はより Pythonic に見えますが、これはもう少し自己文書化されている可能性があります。