7

次のような辞書のリストがあります。

 data = [{'x': 1, 'y': 10},
         {'x': 3, 'y': 15},
         {'x': 2, 'y': 1},
          ... ]

と値matplotlib.axis.plotのリストを必要とする関数 (たとえば) があります。だから私は辞書を「転置」しなければならない」.xy

最初の質問: この操作を何と呼びますか? 「トランスポーズ」は正しい用語ですか?

私はこれを試しましたが、効率的な方法を探しています(おそらくいくつかの特別なnumpy機能があります):

x = range(100)
y = reversed(range(100))
d = [dict((('x',xx), ('y', yy))) for (xx, yy) in zip(x,y)]
# d is [{'y': 99, 'x': 0}, {'y': 98, 'x': 1}, ... ]

timeit.Timer("[dd['x'] for dd in d]", "from __main__ import d").timeit()
# 6.803985118865967

from operator import itemgetter
timeit.Timer("map(itemgetter('x'), d)", "from __main__ import d, itemgetter").timeit()
# 7.322326898574829

timeit.Timer("map(f, d)", "from __main__ import d, itemgetter; f=itemgetter('x')").timeit()
# 7.098556041717529

# quite dangerous
timeit.Timer("[dd.values()[1] for dd in d]", "from __main__ import d").timeit()
# 19.358459949493408

より良い解決策はありますか?私の疑問は次のとおりです。これらの場合、文字列のハッシュは'x'毎回再計算されますか?

4

3 に答える 3

1

この回答からフォームを盗む

import timeit
from operator import itemgetter
from itertools import imap

x = range(100)
y = reversed(range(100))
d = [dict((('x',xx), ('y', yy))) for (xx, yy) in zip(x,y)]
# d is [{'y': 99, 'x': 0}, {'y': 98, 'x': 1}, ... ]
D={x:y for x,y in zip(range(10),reversed(range(10)))}


def test_list_comp(d):
    return [dd['x'] for dd in d]

def test_list_comp_v2(d):
    return [(x["x"], x["y"]) for x in d]

def testD_keys_values(d):
    return d.keys()

def test_map(d):
    return map(itemgetter('x'), d)

def test_positional(d):
    return [dd.values()[1] for dd in d]

def test_lambda(d):
    return list(imap(lambda x: x['x'], d))

def test_imap_iter(d):
    return list(imap(itemgetter('x'), d))

for test in sorted(globals()):
    if test.startswith("test_"):
        print "%30s : %s" % (test, timeit.Timer("f(d)", 
              "from __main__ import %s as f, d" % test).timeit())
for test in sorted(globals()):
    if test.startswith("testD_"):
        print "%30s : %s" % (test, timeit.Timer("f(D)", 
              "from __main__ import %s as f, D" % test).timeit())

次の結果が得られます。

    test_imap_iter : 8.98246016151
       test_lambda : 15.028239837
    test_list_comp : 5.53205787458
 test_list_comp_v2 : 12.1928668102
          test_map : 6.38402269826
   test_positional : 20.2046790578
 testD_keys_values : 0.305969839705

明らかに最大のメリットは、データを必要な形式に近づけることですが、それを制御できない場合があります。

その名の通り、私はそれを変身と呼んでいます。

于 2012-09-06T15:02:23.720 に答える
0

値を反復処理する必要がある場合は、次の方法を検討できます。

imap(lambda x: x['x'], d)
于 2012-09-06T13:23:39.693 に答える
0

なぜこのようなものではないのですか?

[(x["x"], x["y"]) for x in d]

x と y の位置を含むタプルのリストを返します。速度についてはわかりませんが、ラムダのオーバーヘッドが取り除かれます。

于 2012-09-06T14:24:24.827 に答える