Нужно записать данные в txt файл наиболее простым путем, а также сделать проверку данных

Рейтинг: 2Ответов: 1Опубликовано: 07.02.2023
def email_gen(list_of_names):
    emails = []
    for i in list_of_names:
        letter = 1
        while i[1] + '.' + i[0][0:letter] + '@company.io' in emails:
            letter+=1
        emails.append(i[1] + '.' + i[0][0:letter] + '@company.io')
    return emails

Функция принимает список списков [['Имя_1', 'Фамилия_1'], ['Имя_2', 'Фамилия_2'], ['Имя_3', 'Фамилия_3']] из имен и фамилий list_of_names. Далее создается пустой список emails, который в ходе выполнения, заполнится почтовыми адресами. Запускается цикл для каждого списка из имени и фамилии ['Имя_1', 'Фамилия_1']. Устанавливается окончание среза letter = 1. Далее проходит проверка на совпадение, если в списке адресов уже есть такой же адрес (например имя и фамилия сотрудников совпадают), то срез i[0][0:letter] увеличивается на 1 символ. После в список адресов добавляется новый адрес. Адреса присваиваются пользователям по следующей формуле: берется фамилия сотрудника, добавляется точка, затем добавляется первая буква имени и остаточная часть '@company.io'. Если имена и фамилии сотрудников совпадают, к первой букве имени добавляется вторая и т.д.

Исходный файл txt выглядит так:

EMAIL, NAME, LAST_NAME, TEL, CITY
, Ivan, Abramov, 7776514, Moscow
, Alexey, Nikolaev, 1348520, Moscow
, Marina, Shapar, 1111110, Moscow
, Dmitriy, Vasilyev, 0000000, Kazan
, Ekaterina, Ilyina, , St.Petersburg
, Anastasiya, Grigoryan, 1928421, Ekaterinburg
, Andrey, Fedorov, 85212384, Minsk
, Alexey, Lisitsyn, 1239532, Tver
, Dariya, Abramova, 7163908, Moscow
, Alexandr, Evdokimov, 482, Volokolamsk
, Nataliya, Kostina, 9031433, Moscow
, Nikolay, Ermolin, 8539233, St.Petersburg
, , , ,
, Vladimir, Solovovo, 4758395, St.Petersburg
, Vladimir, Ivanov, 4827594, Novosibirsk
, Sergey, Nikolaev, 1294375, Sarov
, Ivan, Ivanov, 8532354, Kazan
, Konstantin, Semenov, 8532286, Moscow
, Grigoriy, Smirnov, 3249235, Kaliningrad
, Vasiliy, , 7123465, Moscow
, Alexandr, Lashko, 9548324, St.Petersburg
, sdfsdf, dwfef, 9994532, Rostov
, Oksana, Edger, 8548433, Kostroma
, Olga, Bogomolova, 8953253, Moscow
, Evgeniy, Strizh, 1123313, Krasnodar
, Valentina, Sergach, 12345567, St.Petersburg
, Polina, Volskaya, 1394542, Vladimir
, Fedor, Malinin, 9453223, Moscow
, Olga, Pahomova, 8543231, Moscow
, ffff, ffff, ffff, fffff
, Stepan, Bogdanov, 4564624, St.Petersburg
, Dmitriy, Smirnov, 9355r24, Kazan
, Valeria, Kolokolkina, 12O4352, St.Petersburg
, Ivan, Sobolev, 2350223, Kirov
, Kristina, Orlova, 1342349, Talnakh
, Alexandr, Ermolin, 2345234, Mozhaysk
, Ekaterina, Vasilevskaya, 9583573, Moscow
, Tatiana, Koroleva, 8674532, Vidnoe
, Elena, Moskvina, 7584294, Moscow
, , , 8954245, Moscow
, Mikhail, Sinev, 5964353, St.Petersburg
, NO_NAME, NO_NAME, 2856735, Kaliningrad
, Anastasiya, Boshich, 9654534, Omsk
, Svetlana, Kapustina, 9476353, Moscow
, Boris, Nikolaev, 9583583, Moscow
, Andrey, Mozgvin, 8537572, Krasnodar
, Oksana, Bogatyreva, 8743565, St.Petersburg
, Kseniya, Nosatenko, 1234194, Yaroslavl
, fwefwgwgwfds, sfewrfw, 9584356, Pskov
, Konstantin, Grigoriev, 1284575, Moscow

Задача звучит так:

Файл представляет собой список данных людей со следующими заголовками:

EMAIL   NAME    LAST_NAME   TEL CITY

Столбец EMAIL пустой у всех. Остальные позиции могут быть заполнены или нет. Представим следующую ситуацию: вы являетесь сотрудником IT отдела некой компании. Ваша компания открывает новый филиал с переводом необходимого количества сотрудников из разных городов. Новый филиал имеет свой почтовый домен. Вам, как сотруднику IT отдела, необходимо создать каждому сотруднику, переходящему в новый филиал, свой уникальный почтовый адрес. У вас есть неотформатированный список сотрудников, который заполняли непонятно как. Также у вас есть кусок кода - функция, которая по имени и фамилии сотрудника составляет его уникальный почтовый адрес. Для выполнения данного задания вам необходимо написать программу, удовлетворяющую следующим требованиям:

  1. Программа должна читать исходный текстовый файл

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

  3. Программа должна заполнить пустой столбец с почтовыми адресами в исходном файле и перезаписать его

  4. Почтовый адрес должен создаваться только для тех, у кого заполнены все остальные поля - Имя, Фамилия, Телефонный номер, Город

  5. Телефонный номер считается валидным, если он состоит из 7 цифр, в противном случае информация невалидна и программа не должна создавать почтовый адрес сотруднику

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

Мой код выглядит следующим образом:

f = open('task_file.txt', 'r+')


def email_gen(list_of_names):
    emails = []
    for i in list_of_names:
        letter = 1
        while i[1] + '.' + i[0][0:letter] + '@company.io' in emails:
            letter += 1
        emails.append(i[1] + '.' + i[0][0:letter] + '@company.io')
    return emails


list_of_names = []

for line in f:
    if line[0] == ',':
        name = []
        coma_index_1 = line[2:]
        first_name = coma_index_1.index(',')
        coma_index_2 = coma_index_1[first_name+2:]
        last_name = coma_index_2.index(',')
        name.append(coma_index_1[:first_name])
        name.append(coma_index_2[:last_name])
        list_of_names.append(name)


for i in list_of_names:
    if '' in i:
        i[0] = 'invalid'
        i[1] = 'invalid'
    elif i[0][0].islower():
        i[0] = 'invalid'
        i[1] = 'invalid'
    elif i[0][1].istitle():
        i[0] = 'invalid'
        i[1] = 'invalid'


emails = email_gen(list_of_names)
f = open('task_file.txt', 'r+')

emails.insert(0, '')
lines_list = []

for line in f:
    lines_list.append(line)

f = open('task_file.txt', 'r+')


for i in lines_list:
    email = emails.pop(0)
    original_line = i
    f.write(email + original_line + '\n')

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

Также непонятно как сделать проверку на корректность столбца с номерами телефонов. Нужно, чтобы на всех строках, где номер телефона состоит не из 7 цифр, отсутствовал мейл или была пометка, что он invalid.

Ответы

▲ 0

Исходные данные по своей структуре являются стандартным CSV файлом. Единственная неприятность - это возможные пробелы после запятой. Но при чтении это решается опцией skipinitialspace=True. Для чтения я бы предпочел csv.DictReader, который вернет список словарей, ключами которых будут заголовки из первой строки файла. В отличии от стандартного csv.reader, это даст возможность обращаться к полям по имени, делая код чуть более читабельным. Код может выглядеть так:

with open('source.txt') as f:
    table = [*csv.DictReader(f, skipinitialspace=True)]

valid_rec = lambda rec: (            
    all(v for k, v in rec.items() if k != 'EMAIL')
    and len(rec['TEL']) == 7
    and rec['TEL'].isnumeric()
)
selected = [*filter(valid_rec, table)]
fio = [(rec['NAME'], rec['LAST_NAME']) for rec in selected]
emails = email_gen(fio)
for rec, email in zip(selected, emails):
    rec['EMAIL'] = email

with open('output.txt', 'w') as f:
    w = csv.DictWriter(f, table[0].keys())
    w.writeheader()
    w.writerows(table)

В этом коде мы исходим из предположения, что данные записаны в 'source.txt', а выгружаются в 'output.txt'. Лямбда-функция valid_rec проверяет, все ли поля кроме EMAIL заполнены, состоит ли телефон из семи символов, и все ли символы телефона - цифры. В отфильтрованном списке будут не копии, а именно записи из исходной таблицы. То есть изменения в них будут отображаться в исходном списке, который в последствии сохраняется. При сохранении словарей используется csv.DictWriter. В отличии от чтения, при записи имена заголовков нужно указывать явно в качестве второго параметра. Равно как запись заголовков нужно делать явно, применив метод writeheader.