1
>>> lst
[('BFD', 0), ('NORTHLANDER', 3), ('HP', 23), ('VOLT', 3)]
>>> min([x for x in lst if x[1]!=0], key=lambda x: x[1])
('NORTHLANDER', 3)
>>>

ここで、min()は1つのセットのみを返します。実際には次のように返されます。

[('NORTHLANDER', 3), ('VOLT', 3)]

この効果のための組み込み関数はありますか?

4

4 に答える 4

8

これは、最初に最小値を計算し、次に最小値を持つすべてのタプルを収集する単純な2段階のソリューションなので、これを行うための独自の関数を記述します。これはかなり特殊な操作であり、汎用min()機能に期待されるものではありません。

最小値の要素を見つけます。

>>> lstm = min([x for x in lst if x[1] > 0], key = lambda x: x[1])
>>> lstm
('NORTHLANDER', 3)

list次に、値が次の値である要素を取得して、新しいリストを作成しlstmます。

>>> [y for y in lst if y[1] == lstm[1]]
[('NORTHLANDER', 3), ('VOLT', 3)]
于 2013-01-04T10:02:39.580 に答える
1

使用collections.defaultdict

d=collections.defaultdict(list)
for item in lst:
    d[item[1]].append(item)
d[min(key for key in d.keys() if key!=0)]

外:

[('NORTHLANDER', 3), ('VOLT', 3)]

テスト

#unwind's solution

def f(lst):
    return [y for y in lst if y[1] == min([x for x in lst if x[1] > 0],
                                             key = lambda x: x[1])[1]]

def f2(lst):
    d=collections.defaultdict(list)
    for item in lst:
        d[item[1]].append(item)
    return d[min(key for key in d.keys() if key!=0)]

%timeit f(lst)
100000 loops, best of 3: 12.1 us per loop
%timeit f2(lst)
100000 loops, best of 3: 5.42 us per loop

つまり、defaultdict2倍以上速いようです。

@martineau最適化を編集します:

def f3(lst):
    lstm = min((x for x in lst if x[1]), key = lambda x: x[1])[1]
    return [y for y in lst if y[1] == lstm]

%timeit f3(lst)
100000 loops, best of 3: 4.19 us per loop

そして、dictを使用した別のベースのソリューションset.defaultはさらに少し高速です:

def f4(lst):
    d={}
    for item in lst:
        if item[1] != 0:
            d.setdefault(item[1],{})[item]=0
    return d[min(d.keys())].keys()

%timeit f4(lst)
100000 loops, best of 3: 3.76 us per loop
于 2013-01-04T10:32:02.353 に答える
0

collections.Counter?同様のデータを処理するために設計されています。

# Instantiate excluding zero length items
>>> c = collections.Counter({k: v for (k, v) in lst if v != 0})
>>> c
Counter({'HP': 23, 'NORTHLANDER': 3, 'VOLT': 3})

# Retrieve most common then reverse it
>>> least_common = c.most_common()[::-1]
[('VOLT', 3), ('NORTHLANDER', 3), ('HP', 23)]

>>> [(k,v) for (k,v) in least_common if v == least_common[0][1]]
[('VOLT', 3), ('NORTHLANDER', 3)]

(これは単なるアイデアであり、効率を上げることを目的としたものではありません)

于 2013-01-04T10:09:41.127 に答える
0

独自のmultimin関数を次のように記述できます。

def multimin(seq, key=None):
    if key is None:
        key = lambda x: x
    min_e = min(seq, key=key)
    return filter((lambda x: key(x) == key(min_e)), seq)

例えば:

>>> lst = [('BFD', 0), ('NORTHLANDER', 3), ('HP', 23), ('VOLT', 3)]
>>> print multimin([x for x in lst if x[1]!=0], key=lambda x: x[1]) 
[('NORTHLANDER', 3), ('VOLT', 3)]
于 2013-01-04T10:13:18.497 に答える