2012-02-08 9 views
-3

1回の呼び出しでタイトルに従って文字列を分割したいとします。私は、リストの内包表記を使用して単純な構文を探していますが、私はまだそれを持っていない:re.splitを使用せずに文字列 "aabbcc" - > ["aa"、 "bb"、 "cc"]を分割します

s = "123456" 

、結果は次のようになります。

["12", "34", "56"] 

私はしたくないもの:

re.split('(?i)([0-9a-f]{2})', s) 
s[0:2], s[2:4], s[4:6] 
[s[i*2:i*2+2] for i in len(s)/2] 

編集

[OK]を、私は六角RGBを解析したかった[A]カラー(および可能であれば他の色/コンポーネント形式)を使用して、すべてのコンポーネントを抽出します。最速のアプローチは、スヴェン・marnachから最後になると思われる :

  1. スヴェン-marnachはxrange:ループあたり0.883マイクロ秒

    python -m timeit -s 's="aabbcc";' '[int(s[i:i+2], 16)/255. for i in xrange(0, len(s), 2)]' 
    
  2. ペア/ ITER:ループ

    あたり1.38マイクロ秒
    python -m timeit -s 's="aabbcc"' '["%c%c" % pair for pair in zip(* 2 * [iter(s)])]' 
    
  3. 正規表現:ループあたり2.55マイクロ秒

    python -m timeit -s 'import re; s="aabbcc"; c=re.compile("(?i)([0-9a-f]{2})"); 
    split=re.split' '[int(x, 16)/255. for x in split(c, s) if x != ""]' 
    
+1

なぜあなたは正規表現を使用することはできませんか? – BoltClock

+0

"aaabbb"を '[" aaa "、" bbb "]'または '[" aa "、" ab "、" bb "]'に分割する必要がありますか?あなたが与えたサンプル実装、特に最後の実装が気に入らないのはなぜですか? –

+0

私は正規表現以外のソリューション(2番目または3番目)に行くだろう...最後の1つはリストの理解です。 –

答えて

4

はコメントを通じて読書、それは実際の問題があるが判明しました。ここではいくつかのオプションは次のとおりです。

def rgba1(s, unpack=struct.unpack): 
    return unpack("BBBB", s.decode("hex")) 

def rgba2(s, int=int, xrange=xrange): 
    return [int(s[i:i+2], 16) for i in xrange(0, 8, 2)] 

def rgba3(s, int=int, xrange=xrange): 
    x = int(s, 16) 
    return [(x >> i) & 255 for i in xrange(0, 32, 8)] 

私が予想したように、最初のバージョンは最速であることが判明:

In [6]: timeit rgba1("aabbccdd") 
1000000 loops, best of 3: 1.44 us per loop 

In [7]: timeit rgba2("aabbccdd") 
100000 loops, best of 3: 2.43 us per loop 

In [8]: timeit rgba3("aabbccdd") 
100000 loops, best of 3: 2.44 us per loop 
1
In [4]: ["".join(pair) for pair in zip(* 2 * [iter(s)])] 
Out[4]: ['aa', 'bb', 'cc'] 

参照:構文という奇妙な "同じstrオーバー2 - iter" のような説明のためHow does zip(*[iter(s)]*n) work in Python?


あなたは「最速の実行を持っている」にしたいコメントで、私はこの実装であることを約束することはできませんが、対策timeitを使用して実行することができますと言います。もちろん、what Donald Knuth said about premature optimisationを覚えておいてください。あなたがそれを明らかにしたので、手元の問題については、r, g, b = s[0:2], s[2:4], s[4:6]が苦労していると思います。

$ python3.2 -m timeit -c ' 
s = "aabbcc" 
["".join(pair) for pair in zip(* 2 * [iter(s)])] 
' 
100000 loops, best of 3: 4.49 usec per loop 

Cf.進RRGGBBAA形式の色定義文字列を解析するための最速の方法は何ですか:

python3.2 -m timeit -c ' 
s = "aabbcc" 
r, g, b = s[0:2], s[2:4], s[4:6] 
' 
1000000 loops, best of 3: 1.2 usec per loop 
+0

本当にこれが範囲[0、len(s)、2)] 'iの' [s [i:i + 2]よりも好ましいと思いますか? –

+0

@SvenMarnach:「好ましい」以上?いいえ、ちょうど代替(と私の小さな心に来た最初のもの)。 – Johnsyweb

0

Numpyは、単一のルックアップのために、お好みのソリューションよりも悪いです:

$ python -m timeit -s 'import numpy as np; s="aabbccdd"' 'a = np.fromstring(s.decode("hex"), dtype="uint32"); a.dtype = "uint8"; list(a)' 
100000 loops, best of 3: 5.14 usec per loop 
$ python -m timeit -s 's="aabbcc";' '[int(s[i:i+2], 16)/255. for i in xrange(0, len(s), 2)]' 
100000 loops, best of 3: 2.41 usec per loop 

しかし、数回のコンバージョンを一度に行うと、numpyははるかに速くなります。

$ python -m timeit -s 'import numpy as np; s="aabbccdd" * 100' 'a = np.fromstring(s.decode("hex"), dtype="uint32"); a.dtype = "uint8"; a.tolist()' 
10000 loops, best of 3: 59.6 usec per loop 
$ python -m timeit -s 's="aabbccdd" * 100;' '[int(s[i:i+2], 16)/255. for i in xrange(0, len(s), 2)]' 
1000 loops, best of 3: 240 usec per loop 

私のコンピュータでは、Numpyの方が2倍以上の方が高速です。 a.shape(number_of_colors, 4)に設定することで簡単に値をグループ化できますが、tolistメソッドを50%遅くします。

実際、ほとんどの場合、配列をリストに変換するのに費やされます。あなたが結果をどうしたいかに応じて、このintermeditaryステップをスキップすることができ、そしていくつかの利点を享受可能性があります

$ python -m timeit -s 'import numpy as np; s="aabbccdd" * 100' 'a = np.fromstring(s.decode("hex"), dtype="uint32"); a.dtype = "uint8"; a.shape = (100,4)' 
100000 loops, best of 3: 6.76 usec per loop 
関連する問題