Объединение вложенных значений словаря на основе регулярных выражений

#python #python-3.x #dictionary

Вопрос:

У меня есть вложенный словарь, содержащий даты и соответствующие им типы объектов (не такие объекты, как в программировании), который выглядит следующим образом:

 dict1 = {0: {'date': ['01', 'MAY', '14', '11MAY', '14', '18', 'MAY', '14'],
             'objecttype': ['Table', 'Anything', 'Chair']},
         1: {'date': ['12', 'MAY', '14', '12MAY14', '15MAY', '14'],
             'objecttype': ['Cup', 'Chair', 'fan']},
         2: {'date': ['05', 'MAY', '14', '13MAY14', '16MAY', '14'],
             'objecttype': ['Home', 'Desk', 'Pencil']},
         3: {'date': ['14', 'MAY', '14', '14MAY', '14', '04MAY14'],
             'objecttype': ['Cup', 'Stationery', 'Book']},
         4: {'date': ['15', 'MAY', '14', '15MAY14', '01', 'MAY', '14'],
             'objecttype': ['Eraser', 'Pen', 'Notebook']}}
 

Все даты и объекты имеют ключи uniques, такие как 0-4.

Как видно, большинство дат не в правильном формате, и для нас правильный формат — [День][Месяц][Год], выглядит так:

04 МАЯ 14

Мой подход к решению этой проблемы заключается в использовании регулярных выражений и двойном циклическом переборе дат. на первом этапе я хочу найти все значения дат, где я нахожу только две цифры, подобные этой, например «04», и объединить их со следующим значением в списке, если он содержит только три алфавита, таких как этот «МАЙ». После этого шага большинство значений даты в dict будут выглядеть так [День][Месяц] .

04 МАЯ

В следующем цикле я хочу найти все экземпляры даты, в которых у нас есть только день и месяц, и объединить их со следующим значением в списке, которое должно быть значением года с двумя цифрами, чтобы в конечном итоге у нас были все даты в этом формате:

04 МАЯ 14

Окончательный диктант будет выглядеть так:

 dict1 = {0: {'date': ['01MAY14', '11MAY14', '18MAY14'],
             'objecttype': ['Table', 'Anything', 'Chair']},
         1: {'date': ['12MAY14', '12MAY14', '15MAY14'],
             'objecttype': ['Cup', 'Chair', 'fan']},
         2: {'date': ['05MAY14', '13MAY14', '16MAY14'],
             'objecttype': ['Home', 'Desk', 'Pencil']},
         3: {'date': ['14MAY14', '14MAY14', '04MAY14'],
             'objecttype': ['Cup', 'Stationery', 'Book']},
         4: {'date': ['15MAY14', '15MAY14', '01MAY14'],
             'objecttype': ['Eraser', 'Pen', 'Notebook']}}
 

У меня возникли проблемы с реализацией этого в python, буду признателен, если кто-нибудь сможет мне помочь. Спасибо

Комментарии:

1. обновил свой ответ.

Ответ №1:

Вы можете использовать дату и время вместо регулярного выражения:

 from datetime import datetime

datetime_object = datetime.strptime('01MAY14', '%d%b%y')
print(datetime_object.strftime('%d/%m/%Y'))
#01/05/2014
 

Более длинный ответ:

 def get_date(d):
    if len(d) == 7:
        return datetime.strptime(d, '%d%b%y')
    else:
        return datetime.strptime(d, '%d%b')

def get_year(l):
    years = list()
    for d in l:
        y = get_date(d).year
        if y and (y not in years) and (y != 1900):
            years  = [get_date(d).year]
    return next(iter(years))

def get_date_with_year(d, y):
    if len(d) == 7:
        return datetime.strptime(d, '%d%b%y')
    else:
        return datetime.strptime(d str(y), '%d%b%Y')

def get_fixed_dates(l):

    year = get_year(l)
    return [get_date_with_year(d, year) for d in l]

l = '9MAY', '12MAY', '15MAY14'
print(get_fixed_dates(l))
#[datetime.datetime(2014, 5, 9, 0, 0), datetime.datetime(2014, 5, 12, 0, 0), datetime.datetime(2014, 5, 15, 0, 0)]
 

Для применения ко всем диктантам:

 def helper(dic):
    dic['date'] = get_fixed_dates(dic['date'])
    return dic
    

new_dict = {k: helper(v) for k, v in dict.items()}
 

Комментарии:

1. В конце концов, таков план, но сначала я должен привести все разбитые даты в формат «01 МАЯ 14». обряд теперь все перепутал.

2. Спасибо, как я могу использовать его для своей проблемы, чтобы он применял функцию для каждого значения даты в словаре. Приношу извинения за вопрос noob, я новичок в словарях.

3. @AliZia обновлено, кстати. это плохая практика-повторно объявлять чистые функции python, например, dict с помощью вашего собственного dict = something использования d = … или чего-то уникального

4. Я думаю, что случай, когда мы находим только значение дня, например «12», упущен. поэтому я получаю ошибку: ошибка значения: данные о времени » 12 «не соответствуют формату» %d%b»

5. Или, может быть, в моих данных есть ненужные значения. Вот почему я хотел пойти с регулярным выражением. но я ценю ваше время и помощь.

Ответ №2:

Сначала вы можете отделить значения цифр от месяца в тексте, а затем перегруппировать:

 import re
def to_dates(d):
   r = [i for a in d for i in re.findall('d |[a-zA-Z] ', a)]
   return [''.join(r[i:i 3]) for i in range(0, len(r), 3)]

dict1 = {0: {'date': ['01', 'MAY', '14', '11MAY', '14', '18', 'MAY', '14'], 'objecttype': ['Table', 'Anything', 'Chair']}, 1: {'date': ['12', 'MAY', '14', '12MAY14', '15MAY', '14'], 'objecttype': ['Cup', 'Chair', 'fan']}, 2: {'date': ['05', 'MAY', '14', '13MAY14', '16MAY', '14'], 'objecttype': ['Home', 'Desk', 'Pencil']}, 3: {'date': ['14', 'MAY', '14', '14MAY', '14', '04MAY14'], 'objecttype': ['Cup', 'Stationery', 'Book']}, 4: {'date': ['15', 'MAY', '14', '15MAY14', '01', 'MAY', '14'], 'objecttype': ['Eraser', 'Pen', 'Notebook']}}
new_dict = {a:{**b, 'date':to_dates(b['date'])} for a, b in dict1.items()}
 

Выход:

 {0: {'date': ['01MAY14', '11MAY14', '18MAY14'], 'objecttype': ['Table', 'Anything', 'Chair']}, 
 1: {'date': ['12MAY14', '12MAY14', '15MAY14'], 'objecttype': ['Cup', 'Chair', 'fan']}, 
 2: {'date': ['05MAY14', '13MAY14', '16MAY14'], 'objecttype': ['Home', 'Desk', 'Pencil']}, 
 3: {'date': ['14MAY14', '14MAY14', '04MAY14'], 'objecttype': ['Cup', 'Stationery', 'Book']}, 
 4: {'date': ['15MAY14', '15MAY14', '01MAY14'], 'objecttype': ['Eraser', 'Pen', 'Notebook']}}