Обойти строку словаря и сохранить как один словарь в Python - PullRequest
0 голосов
/ 05 июня 2019

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

пример:

filtered_data = '''[
   {
      "_id":"1231",
      "address":"akjd-dfdkfj",
      "body":"Your one time password is "sdkd". Enter this in the form to confirm your value.",
      "date":"Thu May 10 23:34:11 GMT+05:30 2018"
   },
   {
      "_id":"1245",
      "address":"sdsd-dgfg",
      "body":"Dear Customer, Reference number is 3435.To check latest status, sms DROP DFGDG on 38388338. Thank you, ABC",
      "date":"Thu May 10 13:22:54 GMT+05:30 2018"
   }
]'''

Код, написанный на данный момент:

import re
id_locs  = [(m.start(0), m.end(0)) for m in re.finditer('_id', filtered_data)]

Как извлечь значение, указав конечную строку как ","?

ожидаемый результат:

{
    "_id": [
        "1231",
        "1245"
    ],
    "_address": [
        "akjd-dfdkfj",
        "sdsd-dgfg"
    ],
    "body": [
        "Your one time password is 'sdkd'. Enter this in the form to confirm your value.",
        "Dear Customer, Reference number is 3435.To check latest status, sms DROP DFGDG on 38388338. Thank you, ABC"
    ],
    "date": [
        "Thu May 10 23:34:11 GMT+05:30 2018",
        "Thu May 10 13:22:54 GMT+05:30 2018"
    ]
}

Ответы [ 4 ]

1 голос
/ 05 июня 2019

Предполагая, что неэкранированные кавычки встречаются только в строках "body", они могут быть зафиксированы в соответствующем JSON и впоследствии проанализированы.Затем у вас есть задача преобразовать список диктов в ряд списков.

import json,re

filtered_data = '''[
   {
      "_id":"1231",
      "address":"akjd-dfdkfj",
      "body":"Your one time password is "sdkd". Enter this in the form to confirm your value.",
      "date":"Thu May 10 23:34:11 GMT+05:30 2018"
   },
   {
      "_id":"1245",
      "address":"sdsd-dgfg",
      "body":"Dear Customer, Reference number is 3435.To check latest status, sms DROP DFGDG on 38388338. Thank you, ABC",
      "date":"Thu May 10 13:22:54 GMT+05:30 2018"
   }
]'''

corrected_data=re.sub("^\s*\"body\":\"(.*)\",",lambda x:"\"body\":\""+x.group(1).replace("\"","'")+"\",",filtered_data,flags=re.M)
dicts_in_list=json.loads(corrected_data)
lists_in_dict={key:[item[key] for item in dicts_in_list] for key in dicts_in_list[0].keys() }
print(lists_in_dict)
0 голосов
/ 05 июня 2019

Это один из подходов с использованием Regex. Получить значения, используя lookahead & lookbehind

Ex:

import re

filtered_data = '''[
   {
      "_id":"1231",
      "address":"akjd-dfdkfj",
      "body":"Your one time password is "sdkd". Enter this in the form to confirm your value.",
      "date":"Thu May 10 23:34:11 GMT+05:30 2018"
   },
   {
      "_id":"1245",
      "address":"sdsd-dgfg",
      "body":"Dear Customer, Reference number is 3435.To check latest status, sms DROP DFGDG on 38388338. Thank you, ABC",
      "date":"Thu May 10 13:22:54 GMT+05:30 2018"
   }
]'''
keys = set(re.findall(r'\"(.+)\":', filtered_data))   #Get Keys
result = {}
for key in keys:
    result[key] = re.findall(r'(?<=\"{}":\")(.*?)(?=\",?)'.format(key), filtered_data)   #Get Values.

print(result)

Выход:

{'_id': ['1231', '1245'],
 'address': ['akjd-dfdkfj', 'sdsd-dgfg'],
 'body': ['Your one time password is ',
          'Dear Customer, Reference number is 3435.To check latest status, sms '
          'DROP DFGDG on 38388338. Thank you, ABC'],
 'date': ['Thu May 10 23:34:11 GMT+05:30 2018',
          'Thu May 10 13:22:54 GMT+05:30 2018']}
0 голосов
/ 05 июня 2019

Решение с регулярными выражениями будет выглядеть так:

patt=re.compile('"([^"]*)"\s*:\s*"(.*?)"(,|\s*\})', re.MULTILINE)
result_dict=dict()
at_end= False
pos= 0
while not at_end:
    matcher= patt.search(filtered_data, pos= pos)
    at_end= matcher is None
    if not at_end:
        key, value, _= matcher.groups()
        result_dict.setdefault(key, list()).append(value)
        _, pos= matcher.span()

Предполагается, что пара ключ-значение всегда заканчивается на "", "или" "\ s *}", как в вашем примереданные.

С findall выглядит немного компактнее:

patt=re.compile('"([^"]*)"\s*:\s*"(.*?)"(,|\s*\})', re.MULTILINE)
result_dict=dict()
for key, value, sep in patt.findall(filtered_data):
    result_dict.setdefault(key, list()).append(value)
0 голосов
/ 05 июня 2019

Если строка сформирует допустимый документ json, вы можете использовать (вам, вероятно, просто нужно добавить '[' и ']' в начале / конце строки:

import json
str2="""[{"_id":"1231","address":"akjd-dfdkfj","body": "Your one time password is sdkd. Enter this in the form to confirm your value.","date":"Thu May 10 23:34:11 GMT+05:30 2018"},{"_id":"1245","address":"sdsd-dgfg","body":"Dear Customer, Reference number is 3435.To check latest status, sms DROP DFGDG on 38388338. Thank you, ABC","date":"Thu May 10 13:22:54 GMT+05:30 2018"}]"""
>>> json.loads(str2, encoding='UTF8')
result_dicts=json.loads(str2)

А затем "объединить" словари в один, например:

result_dict= dict()
for res_dict in result_dicts:
    for key, value in res_dict.items():
        result_dict.setdefault(key, list()).append(value)

Но если ваша примерная строка действительно выглядит в вашем описании, она не является допустимой строкой json из-за неправильного использования двойных кавычек (например, в "Ваш одноразовый пароль -" sdkd ". Введите это в форму для подтверждения ваша ценность. "), вам нужно разобрать ее самостоятельно.

Чтобы применить регулярное выражение, нужно сделать некоторые предположения, чтобы разрезать строку на правильные части. Например. Можно ли предположить, что значение поля всегда заключено в двойные кавычки? Или вы можете предположить, что значение поля никогда не содержит комбинаций символов <",> и <"}> (я использую <> для ограничения строки)?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...