7

これは、いくつかの問題に非常に便利です。

>>> re.search('(?P<b>.b.).*(?P<i>.i.)', 'abcdefghijk').groupdict()
{'i': 'hij', 'b': 'abc'}

しかし、事前にどのような順序を期待すべきかわからない場合はどうなりますか?

[アップデート]

たとえば、未知の順序の文字を含む入力変数があり、「b」が「i」の後に来る場合があります。'.b。'のグループを引き続き参照できるようにしたい そして私。' 入力変数の順序に従って正規表現を順序付ける必要はありません。だから、私はこのようなことをしたいのですが、それが可能かどうかはわかりません:

>>> re.search('(?P<b>.b.)|(?P<i>.i.)', unknown_order_alphabet_str).groupdict()
{'i': 'hij', 'b': 'abc'}

【更新終了】

私は周りを探し回って頭を悩ませましたが、良いリードを生み出すことができません。この機能を推測することはおそらく存在しないでしょう。おそらくこれを行う唯一の方法は、グループごとに文字列全体を1回スキャンすることです(もちろん、代わりにループで実行できます)が、stackoverflowの頭脳が何であるかがわかると思いましたそれについて言わなければなりませんでした。

助けてくれてありがとう、
ジョシュ

4

5 に答える 5

1

REパターンで縦棒(「または」)を使用し、finditer関心のあるすべての一致オブジェクトを取得します。それぞれに、その一致に関与しないグループの値としてgroupdictwithNoneがあり、必要に応じてdictを「マージ」できます。 。

例えば:

import re

def mergedgroupdict(pattern, thestring):
  there = re.compile(pattern)
  result = {}
  for mo in there.finditer(thestring):
    d = mo.groupdict()
    for k in d:
      if k not in result and d[k] is not None:
        result[k] = d[k]
  return result

これは、パターン内の名前付きグループごとに最初の実際の一致を選択するだけのマージ戦略を使用します。今例えば

>>> mergedgroupdict('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')
{'i': 'hij', 'b': 'abc'}
>>> mergedgroupdict('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk'[::-1])
{'i': 'jih', 'b': 'cba'}

私があなたの質問を正しく解釈すれば、おそらくあなたが望むように。

于 2010-02-02T22:07:38.103 に答える
0
>>> [m.groupdict() for m in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

うまく機能しているようですが、多くのグループがある場合、どれが面倒ではないかをチェックするのはNone面倒かもしれません。

これにより、文字列内の.b.すべての.i.一致が検索されます。それぞれが1つ見つかったことを確認したい場合は、それも手動で確認する必要があります。

于 2010-02-02T22:06:58.503 に答える
0

私が得ることができる最も近いものはこれです:

>>> [match.groupdict() for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

辞書をどのように組み合わせるかは、複数の一致を期待しているかどうかによって異なります。それぞれ1つの一致のみが必要な場合は、次のように実行できます。

>>> results = {}
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk'):
...     results.update(dict((k,v) for k, v in match.groupdict().iteritems() if v is not None))
... 
>>> results
{'i': 'hij', 'b': 'abc'}

または複数の試合の場合:

>>> results = defaultdict(lambda: [])
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijkabcdefghijk'):
...     for k, v in match.groupdict().iteritems():
...         if v is not None:
...             results[k].append(v)
... 
>>> results
defaultdict(<function <lambda> at 0x7f53d0992c08>, {'i': ['hij', 'hij'], 'b': ['abc', 'abc']})
于 2010-02-02T22:08:40.003 に答える
0

finditerこれは、辞書のマージも必要としない方法です。

>>> pat = re.compile(r'(?:.*?(?:(?P<b>.b.)|(?P<i>.i.))){2}')

>>> pat.search('abcdefghijk').groupdict()
{'i': 'hij', 'b': 'abc'}

>>> pat.search('aicdefghbjk').groupdict()
{'i': 'aic', 'b': 'hbj'}

bこれは、各文字を想定してiおり、文字列に1回だけ表示されます。それ以外の場合は、次のようになります。

  • 文字の1つが欠落している可能性がある場合は、の{,2}代わりに使用できます{2}
  • いずれかの文字が複数回出現する場合、検索ではいずれかの文字の最初の2つの出現が取得されます(たとえば、b2回検出されても、まったく検出iされない場合があります)。
于 2013-02-27T13:11:53.753 に答える
0

これは、1回のスワイプでゲームに遅れて登場した人で、初心者でも読むことができます。

>>> dict([(name, re.search(pattern, "abcdefghijk").group())
          for name, pattern in {"b": ".b.", "i": ".i"}.items()])  
{'b': 'abc', 'i': 'hij'}
于 2017-08-05T10:19:55.917 に答える