Python: условие регулярного выражения для поиска строчных букв / ди git перед заглавной буквой - PullRequest
0 голосов
/ 25 февраля 2020

Я хотел бы разбить строку в python и превратить ее в словарь так, чтобы ключом был любой фрагмент символов между двумя заглавными буквами, а значением должно быть число вхождений этого фрагмента в строку.

В качестве примера: string = 'ABbACc1Dd2E' должно возвращать это: {'A': 2, 'Bb': 1, 'Cc1': 1, 'Dd2': 1, 'E': 1}

Я нашел два рабочих решения (см. Ниже), но я ищу более общее / элегантное решение для это, возможно, условие регулярного выражения в одну строку.

Спасибо

Ответы [ 2 ]

2 голосов
/ 25 февраля 2020

Раствор 1

string = 'ABbACc1Dd2E'
string = ' '.join(string)

for ii in re.findall("([A-Z] [a-z])",string) + \
          re.findall("([A-Z] [0-9])",string) + \
          re.findall("([a-x] [0-9])",string):
            new_ii = ii.replace(' ','')
            string = string.replace(ii, new_ii)

string = string.split()
all_dict = {}
for elem in string:
    all_dict[elem] = all_dict[elem] + 1 if elem in all_dict.keys() else 1 

print(all_dict)

{'A': 2, 'Bb': 1, 'Cc1': 1, 'Dd2': 1, 'E': 1}

Раствор 2

string = 'ABbACc1Dd2E'
all_upper = [ (pos,char) for (pos,char) in enumerate(string) if char.isupper() ]

all_dict = {}
for (pos,char) in enumerate(string):
    if (pos,char) in all_upper:
        new_elem = char
    else:
        new_elem += char

    if pos < len(string) -1 :
        if  string[pos+1].isupper():
            all_dict[new_elem] = all_dict[new_elem] + 1 if new_elem in all_dict.keys() else 1 
        else:
            pass
    else:
        all_dict[new_elem] = all_dict[new_elem] + 1 if new_elem in all_dict.keys() else 1 

print(all_dict)

{'A': 2, 'Bb': 1, 'Cc1': 1, 'Dd2': 1, 'E': 1}

0 голосов
/ 26 февраля 2020

Спасибо usr2564301 за это предложение:

Правильное регулярное выражение равно '[A-Z][a-z]*\d*'

import re

string = 'ABbACc1Dd2E'
print(re.findall(r'[A-Z][a-z]*\d*', string))
['A', 'Bb', 'A', 'Cc1', 'Dd2', 'E']

Затем можно использовать itertools. groupby для создания итератора, который возвращает последовательные ключи и группы из итерируемого.

from itertools import groupby

all_dict = {}
for i,j in groupby(re.findall(r'[A-Z][a-z]*\d*', string)):
    all_dict[i] = all_dict[i] + 1 if i in all_dict.keys() else 1 
print(all_dict)
{'A': 2, 'Bb': 1, 'Cc1': 1, 'Dd2': 1, 'E': 1}

В конечном счете, можно использовать sorted(), чтобы получить это в одной строке с правильным подсчетом:

print({i:len(list(j)) for i,j in groupby(sorted(re.findall(r'[A-Z][a-z]*\d*', string))) })
{'A': 2, 'Bb': 1, 'Cc1': 1, 'Dd2': 1, 'E': 1}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...