web-dev-qa-db-ja.com

Pythonタプルで順序が保持されていることを期待できますか?

タイムセグメントを作成する日時のリストがあります。つまり、_[t0, t1, ... tn]_を[(t0,t1),(t1,t2),...,(tn-1, tn)]に変換します。私はそれをこのようにしました:

_# start by sorting list of datetimes
mdtimes.sort()
# construct tuples which represent possible start and end dates

# left edges
dtg0 = [x for x in mdtimes]
dtg0.pop()

# right edges
dtg1 = [x for x in mdtimes]
dtg1.reverse()
dtg1.pop()
dtg1.sort()

dtsegs = Zip(dtg0,dtg1)
_

質問...

  1. この方法で作成した後、任意の(tn-1、tn)についてtn-1 <tnを当てにすることはできますか? (注文は保持されますか?)
  2. 元のmdtimesリストをリスト内包表記でコピーするのは良い習慣ですか?そうでない場合、それはどのように行われるべきですか?
  3. これらのタプルを作成する目的は、タプルを反復処理し、データセットを_tn-1_およびtnでセグメント化することです。これは合理的なアプローチですか?つまり.

    _datasegment = [x for x in bigdata if ( (x['datetime'] > tleft) and (x['datetime'] < tright))] 
    _

ありがとう

26
Pete
  1. タプルの順序は、タプルに値を挿入するときです。あなたが求めていると思うように、それらはソートされません。 Zipは、値を挿入した順序を保持します。

  2. これは許容できる方法ですが、2つの代替案があります。 copy モジュールを使用するか、dtg1 = mdtimes[:]を使用します。

  3. 合理的に聞こえます。

17
marcog

listTupleの両方が順序付けられています。

dtg0, dtg1 = itertools.tee(mdtimes)
next(dtg0)
dtsegs = Zip(dtg0, dtg1)

Zipでも同じことができます。

>>> l = ["t0", "t1", "t2", "t3", "t4", "t5", "t6"]
>>> Zip(l[::2], l[1::2])
[('t0', 't1'), ('t2', 't3'), ('t4', 't5')]
6
Paweł Nadolski

代わりに:_dtg0 = [x for x in mdtimes]_、_dtg0 = mdtimes[:]_は、あるリストを別のリストにコピーするだけなので、そうします。注:Python 3.3から、newlist = oldlist.copy()とだけ言うことができます

順序に関しては、Zipの順序が明確に定義されており、リストとタプルの両方が順序付けられたコレクションであるため、ここでは問題はありません。

4
Eli Bendersky

(x1、x2、x3、...)を[(x1、x2)、(x2、x3)、...]に変換することはペアワイズの組み合わせと呼ばれ、非常に一般的なパターンであるため、 itertools ドキュメントはレシピを提供します:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

for ta, tb in pairwise(mdtimes): 
    ....
3
tokland

これは「これは合理的なアプローチですか?」という質問への回答です(これはすべての人に無視されているようです)

要約:mdtimesからペアワイズのものを作ることから、包括的問題(bigdataのセグメント化)に視線を上げる必要があるかもしれません。

詳細:

結果の望ましい使用法は次のように表されます。

_datasegment = [x for x in bigdata if ( (x['datetime'] > tleft) and (x['datetime'] < tright))] 
_

これは次のように表現されます。

_datasegment = [x for x in bigdata if tleft < x['datetime'] < tright] 
_

現状では、タイムスタンプが境界点の1つと正確に等しい場合は含まれないため、次のように変更してみましょう。

_datasegment = [x for x in bigdata if tleft <= x['datetime'] < tright]
_

しかし、それはループに現れるでしょう:

_for tleft, tright in dtsegs:
    datasegment = [x for x in bigdata if tleft <= x['datetime'] < tright]
    do_something_with(datasegment)
_

おっと! len(bigdata) * len(dtsegs)に比例して時間がかかります...len(bigdata)len(dtsegs)の値は何でしょうか?

bigdataがソートされている場合、実行したいことはNに比例する時間で実行できます。ここで、N = len(bigdata)です。 bigdataがまだソートされていない場合は、N * log(N)に比例して時間でソートできます。

あなたは別の質問をしたいかもしれません...

タイムスタンプ<min(mdtimes)または> = max(mdtimes)を持つbigdata内のアイテムは、どのデータセグメントにも含まれないことも指摘しておく価値があります...これは意図的なものですか?

3
John Machin

私は専門家ではありませんが、リストをコピーしてから2つのリストから取得したペアの新しいリストを作成することで、メモリ要件を4倍にしませんか?次のことをしてみませんか。

dtsegs = [(dtg0[i], dtg0[i+1]) for i in range(len(dtg0)-1)]

でも、それがいかに「Pythonic」なのかわからない。

編集:実際、このタプルのリストで何をする必要があるかを見ると、この[i]と[i + 1]をそのレベルで直接実行でき、この新しい構造をまったく作成することさえできません。あなたが扱っている日付の数はわかりませんが、それが少し少ない場合は、実際には問題ではないと思います。

価値があるので、ここにいる他の回答者のカップルはあなたの質問を誤解しているようですが、私はまだ十分な評判を持っていないので彼らの投稿にコメントすることはできません:) Ignacio Vazquez-Abramsの解決策は私にとって最良のようです、彼の「next(dtg0)」はおそらく「next(dtg1)」(?)

1
flamingspinach