Возможный получить произвольный незаказанный набор именованных групп в одном налете с модулем ре Python?

Это супер удобно для некоторых проблем:

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

Но что, если я не знаю что порядок ожидать заранее?

[обновление]

Например, скажите, что у меня есть входная переменная, содержащая некоторый неизвестный порядок символов, и это именно так происходит, что 'b' прибывает после того, как 'я'. Я хочу все еще смочь сослаться на группы для '.b'. и '.i'. не имея необходимость заказывать мой regex согласно их порядку во входном var. Так, мне жаль, что я не мог сделать что-то вроде этого, но я не знаю, возможно ли это:

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

[закончите обновление]

Я искал вокруг и ломал голову набор, но не могу генерировать пользу, ведет. Предположение этой функциональности не существовало бы, потому что, вероятно, единственный путь к ре, чтобы сделать это должно просканировать всю строку однажды для каждой группы (который, конечно, я мог сделать в цикле вместо этого), но я думал, что буду видеть то, что stackoverflow мозг должен был сказать об этом.

Спасибо за помощь,
Josh

6
задан 2 February 2010 в 22:11
поделиться

3 ответа

Я верю, что вы хотите что-то такое:

public partial class Sample: UserControl
{
    public event EventHandler TextboxValidated;

    public Sample()
    {
        InitializeComponent();
    }


    private void TextBox_Validated(object sender, EventArgs e)
    {
        // invoke UserControl event here
        if (this.TextboxValidated != null) this.TextboxValidated(sender, e);
    }
}

И затем на вашей форме:

public partial class MainForm : Form
{
    private Sample sampleUserControl = new Sample();

    public MainForm()
    {
        this.InitializeComponent();
        sampleUserControl.TextboxValidated += new EventHandler(this.CustomEvent_Handler);
    }
    private void CustomEvent_Handler(object sender, EventArgs e)
    {
        // do stuff
    }
}
-121--1642055-
>>> [m.groupdict() for m in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

Кажется, работает хорошо, хотя если у вас есть много групп, проверяющих, какая из них не Нет может стать утомительным.

При этом будут найдены все .b. и все .i. соответствует в последовательности. Если вы хотите быть уверены, что он нашел один из каждого вы должны будете проверить это вручную, тоже.

-121--4518441-

Используйте вертикальную полосу («или») в образец RE и finditer , чтобы получить все интересующие объекты соответствия: каждый из них будет иметь groupdict с None в качестве значения для групп, не участвующих в этом совпадении, и вы можете «объединить» символы по своему усмотрению.

Например,

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'}

предположительно, как вы хотите, если я правильно интерпретирую ваш вопрос.

1
ответ дан 17 December 2019 в 22:13
поделиться

Ближе всего я могу предложить следующее:

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

То, как вы объедините словари, зависит от того, ожидаете ли вы более одного совпадения. Если вам нужно только одно совпадение, вы можете сделать:

>>> 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']})
0
ответ дан 17 December 2019 в 22:13
поделиться
>>> [m.groupdict() for m in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

Кажется, все работает нормально, хотя, если у вас есть много групп, проверяющих, какая из них не Нет может стать утомительным.

Это находит все .b. и все .i. соответствует в строке. Если вы хотите быть уверены, что найден один из них, вам также придется проверить это вручную.

0
ответ дан 17 December 2019 в 22:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: