10

私は単に次のようなことをする単純な「パーサー」を持っています:
[x.split('=') for x in mystring.split(',')]

ただし、mystringは次のようなものにすることができます
'foo=bar,breakfast=spam,eggs'

明らかに、
素朴なスプリッターはそれをしません。これについては、 Python 2.6 標準ライブラリに限定されているため、
たとえばpyparsingは使用できません。

期待される出力は
[('foo', 'bar'), ('breakfast', 'spam,eggs')]

私は正規表現でこれをやろうとしていますが、次の問題に直面しています:

私の最初の試み
r'([a-z_]+)=(.+),?'
は私に与えました
[('foo', 'bar,breakfast=spam,eggs')]

明らかに、
貪欲.+でなくても問題は解決しません。

だから、
どういうわけか最後のコンマ (または$) を必須にする必要があると思います。
それだけでは実際には機能しません。それと 同様
r'([a-z_]+)=(.+?)(?:,|$)'
に、コンマを含む値のコンマの後ろのものは省略されます。
[('foo', 'bar'), ('breakfast', 'spam')]

何らかの後読み (?) 操作を使用する必要があると思います。
質問
1.どちらを使用しますか? または
2.それ/これを行うにはどうすればよいですか?

編集

以下のdaramarakの回答に基づいて、私はabarnertが後で少し冗長な形式で提案
した のとほとんど同じことをすることになりました。

vals = [x.rsplit(',', 1) for x in (data.split('='))]
ret = list()
while vals:
    value = vals.pop()[0]
    key = vals[-1].pop()
    ret.append((key, value))
    if len(vals[-1]) == 0:
        break

編集2:

私の好奇心を満たすために、これは実際に純粋な正規表現で可能ですか? つまりre.findall()、2タプルのリストを返すでしょうか?

4

5 に答える 5

4

ダラマラクの答えは、ほとんど機能するか、そのまま機能します。サンプル出力の形式と手順のあいまいな説明から判断するのは困難です。しかし、それがほとんど動作するバージョンであれば、簡単に修正できます。

それをコードに入れる:

>>> bits=[x.rsplit(',', 1) for x in s.split('=')]
>>> kv = [(bits[i][-1], bits[i+1][0]) for i in range(len(bits)-1)]

最初の行は(私が信じている)daramarakの答えです。単独で、最初の行は の(value_i, key_i+1)代わりに のペアを提供します(key_i, value_i)。2行目は、そのための最も明白な修正です。それがどのように機能するかを確認するために、より多くの中間ステップと少しの出力を使用します。

>>> s = 'foo=bar,breakfast=spam,eggs,blt=bacon,lettuce,tomato,spam=spam'
>>> bits0 = s.split('=')
>>> bits0
['foo', 'bar,breakfast', 'spam,eggs,blt', 'bacon,lettuce,tomato,spam', 'spam']
>>> bits = [x.rsplit(',', 1) for x in bits0]
>>> bits
[('foo'), ('bar', 'breakfast'), ('spam,eggs', 'blt'), ('bacon,lettuce,tomato', 'spam'), ('spam')]
>>> kv = [(bits[i][-1], bits[i+1][0]) for i in range(len(bits)-1)]
>>> kv
[('foo', 'bar'), ('breakfast', 'spam,eggs'), ('blt', 'bacon,lettuce,tomato'), ('spam', 'spam')]
于 2013-02-01T08:14:01.253 に答える
1

以前のように分割操作を使用することをお勧めします。ただし、最初に等号で分割し、次に右端のカンマで分割して、左右の文字列の単一のリストを作成します。

input =
"bob=whatever,king=kong,banana=herb,good,yellow,thorn=hurts"

最初に分割されます

first_split = input.split("=")
#first_split = ['bob' 'whatever,king' 'kong,banana' 'herb,good,yellow,thorn' 'hurts']

次に、右端のコンマで分割すると、次のようになります。

second_split = [single_word for sublist in first_split for item in sublist.rsplit(",",1)]
#second_split = ['bob' 'whatever' 'king' 'kong' 'banana' 'herb,good,yellow' 'thorn' 'hurts']

次に、次のようにペアを収集します。

pairs = dict(zip(second_split[::2],second_split[1::2]))
于 2013-02-01T07:53:06.140 に答える
0

これを試してもらえますか、それは私にとってはうまくいきました:

mystring = "foo=bar,breakfast=spam,eggs,e=a"
n = []
i = 0

for x in mystring.split(','):
    if '=' not in x:
        n[i-1] = "{0},{1}".format(n[i-1], x)
    else:
        n.append(x)
        i += 1
print n

次のような結果が得られます。

  ['foo=bar', 'breakfast=spam,eggs', 'e=a']

次に、リストに移動して、必要なことを実行できます。

于 2013-02-01T08:12:18.057 に答える
0

キーの名前に が含まれていないと仮定すると、次のシーケンスで がなくて,も で分割でき、が続きます。,,==

re.split(r',(?=[^,=]+=)', inputString)

(これは私の元のソリューションと同じです。 orre.splitではなく、使用されることを期待しています)。re.findallstr.split

完全なソリューションは、ワンライナーで実行できます。

[re.findall('(.*?)=(.*)', token)[0] for token in re.split(r',(?=[^,=]+=)', inputString)]
于 2013-02-01T13:23:50.167 に答える