Цикл прилип к последней записи Python - PullRequest
0 голосов
/ 04 июля 2018

Я читаю файл и хочу добавить данные в массив, а затем выгрузить их в файл json. Я использую Python 2.7.

Проблема в том, что он возвращает только последнюю строку файла и заполняет файл этим. Не знаю, понятно ли это, поэтому я показываю код

import re
import json

results = []
contact = {
    "id":"",
    "email":""
}


source = open('zen_id.txt')
output = open('zen_id_js.json', 'w')
for line in source:
    email = re.search(r'[\w\.-]+@[\w\.-]+', line)
    contact['email'] = email.group(0)
    p = re.search(r'\d\d\d\d\d', line)
    contact['id'] = p.group(0)
    results.append(contact)

json.dump(results, output)

И вывод:

[
  {
    "id": "35148",
    "email": "****@gmail.com"
  },
  {
    "id": "35148",
    "email": "****@gmail.com"
  },
  {
    "id": "35148",
    "email": "****@gmail.com"
  },
  {
    "id": "35148",
    "email": "****@gmail.com"
  },

Кто-нибудь знает, что происходит?

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Вы должны добавить словарь контактов внутри цикла for.

import re
import json

results = []



source = open('zen_id.txt')
output = open('zen_id_js.json', 'w')
for line in source:
    contact = {
        "id": "",
        "email": ""
    }
    email = re.search(r'[\w\.-]+@[\w\.-]+', line)
    contact['email'] = email.group(0)
    p = re.search(r'\d\d\d\d\d', line)
    contact['id'] = p.group(0)
    results.append(contact)

json.dump(results, output)
0 голосов
/ 04 июля 2018

Вы можете выполнить глубокую копию.

  import re
  import json
  import copy

  results = []
  contact = {
      "id":"",
      "email":""
  }


  source = open('zen_id.txt')
  output = open('zen_id_js.json', 'w')
  for line in source:
      email = re.search(r'[\w\.-]+@[\w\.-]+', line)
      contact['email'] = email.group(0)
      p = re.search(r'\d\d\d\d\d', line)
      contact['id'] = p.group(0)
      results.append(copy.deepcopy(contact))

  json.dump(results, output)
0 голосов
/ 04 июля 2018

делая

contact = {
    "id":"",
    "email":""
}

вне цикла, у вас есть один экземпляр объекта. Вы просто изменяете один и тот же экземпляр снова и снова (result.append не создает копию словаря, только сохраняет ссылку)

Одним из решений является определение его внутри цикла или создание копии

for line in source:
    email = re.search(r'[\w\.-]+@[\w\.-]+', line)
    contact = {}  # create a new, empty instance
    contact['email'] = email.group(0)
    ...

обратите внимание, что нет необходимости определять словарь с ключами и пустыми значениями, так как вы все равно перезаписываете их. Определите это пустым.

Другая альтернатива - вообще не использовать contact и создавать словарь на лету, используя буквальную форму при добавлении в список:

results.append({"email":email.group(0), "id":p.group(0)})

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

results = [{"email":re.search(r'[\w\.-]+@[\w\.-]+', line).group(0), "id":re.search(r'\d\d\d\d\d', line).group(0)} for line in source]

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

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