1

tから開始してsになるエレガントな方法を見つけることができないようです。

>>>t = ['a',2,'b',3,'c',4]
#magic
>>>print s
{'a': 2, 'c': 4, 'b': 3}

私が思いついたソリューションは、エレガントではないようです:

s = dict()
for i in xrange(0, len(t),2): s[t[i]]=t[i+1]
# or something fancy with slices that I haven't figured out yet

明らかに簡単に解決できますが、もっと良い方法があるようです。ある?

4

6 に答える 6

10

私は を使用itertoolsしますが、それが複雑だと思う場合 (コメントで示唆したように)、おそらく:

def twobytwo(t):
  it = iter(t)
  for x in it:
    yield x, next(it)

d = dict(twobytwo(t))

または同等に、再び itertools に戻ります。

def twobytwo(t):
  a, b = itertools.tee(iter(t))
  next(b)
  return itertools.izip(a, b)

d = dict(twobytwo(t))

または、インラインであることを主張する場合は、季節に適した「トリック・オア・トリート」ムードで:

d = dict((x, next(it)) for it in (iter(t),) for x in it)

私はこれをトリックだと考えていますが、一部の人はそれをご馳走だと思うかもしれません. IOW、私はこの種のことを怖いと思いますが、どうやらアメリカではこの時期に物事が起こるはずです;-)。

基本的に、問題は「リストを一度に 2 項目ずつ移動するにはどうすればよいか」にdict要約されます。ここで示しているすべてのソリューションでは、余分なスペースのみが確保されます (もちろん、入力リストと出力辞書に必要なO(1)スペースを超えて)。O(N)

ドキュメントで提案されているアプローチ(誰もがそのページ、 itertool レシピに精通している必要があります) は、pairwiseそのページの関数であり、基本的にここで提案した 2 番目のものです。すべての site-packages ディレクトリには、これらのレシピを含むファイルが含まれている必要があると思いますiterutils.py(そのようなファイルがまだ python の stdlib に含まれていないのは残念です!-)。

于 2009-10-29T02:03:12.737 に答える
9

Lukáš Lalinský's answerと同じ考え、異なるイディオム:

>>> dict(zip(*([iter(t)] * 2)))
{'a': 2, 'c': 4, 'b': 3}

これはdictzipおよびiter関数を使用します。Lukášの答えよりも優れているのは、どのイテラブルでも機能することです。使い方:

  1. iter(t)list に対して反復子を作成しますt
  2. [iter(t)] * 2同じ反復子を参照する 2 つの要素を持つリストを作成します。
  3. zip2 つの iterable オブジェクトを取り、それらの要素をペアにする関数です: 最初の要素は一緒に、2 番目の要素は一緒に、というように、1 つの iterable が使い果たされるまで。
  4. zip(*([iter(t)] * 2))の両方の引数として同じ反復子tが渡されます。したがって、 の最初と 2 番目の要素を取り、それらをペアにします。そして、3番目と4番目。そして、5番目と6番目など。zipzipt
  5. dictペアを含む(key, value)イテラブルを取り、それらからディクショナリを作成します。
  6. dict(zip(*([iter(t)] * 2)))OPの要求に応じて辞書を作成します。
于 2009-10-28T20:13:45.077 に答える
7

正確には効率的ではありませんが、非常に大きなリストには必要ない場合:

dict(zip(t[::2], t[1::2]))

または、ジェネレーターを使用したバージョン:

dict(t[i:i+2] for i in xrange(0, len(t), 2))
于 2009-10-28T20:09:07.640 に答える
6

みんな、みんな、itertoolsを使ってください。低 RAM ユーザーは、リストが大きくなると感謝するでしょう。

>>> from itertools import izip, islice
>>> t = ['a',2,'b',3,'c',4]
>>> s = dict(izip(islice(t, 0, None, 2), islice(t, 1, None, 2)))
>>> s
{'a': 2, 'c': 4, 'b': 3}

見栄えが悪いかもしれませんが、不要なメモリ内コピーは作成されません。

于 2009-10-28T20:17:21.230 に答える
2

ストリームモジュールの使用:

>>> from stream import chop
>>> t = ['a',2,'b',3,'c',4]
>>> s = t >> chop(2) >> dict
>>> s
{'a': 2, 'c': 4, 'b': 3}

このモジュールはかなりあいまいであり、政治的に正しいと一般に考えられている Python の「規則に従っている」わけではないことに注意してください。したがって、Python を学習しているだけの場合は、このルートに進まないでください。標準ライブラリにあるものに固執します。

于 2010-05-31T07:16:36.220 に答える
1
dict(zip(t[::2], t[1::2]))

おそらく最も効率的ではありません。Python 3 で動作します。Python 2.x では、zip をインポートする必要がある場合があります。

于 2009-10-28T20:11:25.047 に答える