Найти - Пользователи
Полная версия: Регулярные выражения
Начало » Python для новичков » Регулярные выражения
1 2
SomethingButNotNickName
Добрый день.
Есть файл в котором строками прописаны сотрудники и их оклад. Причем между фамилией и именем может быть какая то еще информация. Какая именно неизвестно. Например строка выглядит так.
 line = 'Петров Герой труда Петр 100000'
Задача по имени вытащить оклад сотрудника.
Как вариант можно пробежать по файлу и проверить каждую строку на наличие в ней интересующей фамилии. Если возвращен список не нулевой длины, т.е. есть совпадение, пробежать повторно уже доставая оклад.

 surname = 'Петров'    # имена и фамилии также хранятся в соответствующих переменных.
import re
if len(re.findall(surname, line)) != 0:
    pay = re.findall(r'\d+', line)
print(pay)

Но в списке могут быть и однофамильцы. Следовательно нужно передать в качестве паттерна две переменных (имя и фамилию). Вот тут я уже теряюсь и прошу помощи.
Так же, насколько я понимаю, в питоне должны поддерживаться условия внутри регулярок. Но заставить их работать тоже не удалось. Можно пример?

py.user.next
Напиши функцию, которая принимает строку файла и возращает словарь, в котором данные из строки разделены по ключам. Потом просто каждую строку передаёшь в эту функцию и в полученном из неё словаре ищешь нужные данные.
SomethingButNotNickName
py.user.next
Напиши функцию, которая принимает строку файла и возращает словарь, в котором данные из строки разделены по ключам. Потом просто каждую строку передаёшь в эту функцию и в полученном из неё словаре ищешь нужные данные.
Как вариант - да.

Ну а насчет регулярок? Такие операции невозможны в питоне?
SomethingButNotNickName
Дело в том, что:
1) условие задачи целиком выглядит так
# Задание-1: Решите задачу (дублированную ниже):

# Дана ведомость расчета заработной платы (файл “data/workers”). Рассчитайте зарплату всех работников,
# зная что они получат полный оклад, если отработают норму часов. Если же они отработали меньше нормы,
# то их ЗП уменьшается пропорционально, а за заждый час переработки они получают удвоенную ЗП,
# пропорциональную норме.
# Кол-во часов, которые были отработаны, указаны в файле “data/hours_of”

# С использованием классов.
# Реализуйте классы сотрудников так, чтобы на вход функции-конструктора каждый работник получал строку из файла
т.е. то, что вы предлагаете засунуть в словарь уже находится внутри класса.
2) половина данных о сотруднике лежит в одном файле, а половина (включая и з/п) в другом.
И мне нужны данные из обоих файлов. А строки в них перемешаны до кучи.
Файлы тоже с датой вложил
SomethingButNotNickName
второй файл
SomethingButNotNickName
Первая копия workers не верная.
Правильная тут
py.user.next
SomethingButNotNickName
т.е. то, что вы предлагаете засунуть в словарь уже находится внутри класса
Это тебе кажется так.

Надо для каждого файла сделать свою функцию обработки его строки. Функция такая: на вход принимается строка файла; на выходе возвращается словарь, в котором поля строки разделены по ключам.
Для каждого файла должна быть своя функция обработки строки этого файла.
Эти функции никакого отношения к твоему заданию не имеют. Они используются для того, чтобы точно работать с данными. Таким образом при чтении первого файла у тебя получаются словари из его строк, и в этих словарях можно легко искать любые поля (фамилию, имя, зарплату, часы), просто обращаясь к ним по именам. С сырой строкой ты этого не сделаешь, даже если сделаешь регулярку, потому что регулярка не будет тебе давать именованных полей.

SomethingButNotNickName
Ну а насчет регулярок?
Регулярки используются только внутри таких функций для разделения строк на поля. Больше нигде. Когда словарь для одной строки файла возвращён, поля в нём разделены точно и имеют удобные имена, поэтому никакие регулярки больше не требуются.

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

Например, ты получил словарь первой строки первого файла и словарь первой строки второго файла. Эти словари разные, но брать поля из них легко. Ты берёшь из них поля (допустим, фамилии) и сравниваешь между собой. Если фамилии одинаковые, значит эти словари относятся к одному работнику и ты можешь из этих словарей брать следующие данные и куда-то их копировать или совместные вычисления проводить. Можно и просто взять два словаря, относящиеся к одному работнику, и сделать из них третий словарь, более полный. Вот твой этот класс, которые требуется в задании, имеет примерно такую структуру - словари из разных файлов, слитые в один словарь, и так по каждому работнику. Только вместо словаря используется класс, у которого внутри хранятся эти данные одного работника. Отличие словаря от класса в том, что класс может меняться по своему устройству, а словарь остаётся неизменным. Но класс может иметь и поведение, тогда как словарь используется только для хорошо структурированного хранения данных.

Пример
Разделение строки
  
>>> import re
>>> 
>>> def split1(s):
...     parts = re.findall(r'^(\S+).*\s(\S+)\s+(\d+)$', s)[0]
...     out = {'surname': parts[0],
...            'firstname': parts[1],
...            'salary': int(parts[2])}
...     return out
... 
>>> 
>>> s = 'Петров Герой труда Петр 100000'
>>> 
>>> d = split1(s)
>>> d
{'surname': 'Петров', 'firstname': 'Петр', 'salary': 100000}
>>> d['salary'] * 2
200000
>>>

Несколько человек из файла
  
>>> import re
>>> 
>>> def split1(s):
...     parts = re.findall(r'^(\S+).*\s(\S+)\s+(\d+)$', s)[0]
...     out = {'surname': parts[0],
...            'firstname': parts[1],
...            'salary': int(parts[2])}
...     return out
... 
>>> 
>>> lst = ['Петров Герой труда Петр 100000',
...        'Иванов Саша 5100',
...        'Сидоров Старик Андрей 12345']
>>> 
>>> out = list(map(split1, lst))
>>> out
[{'surname': 'Петров', 'firstname': 'Петр', 'salary': 100000}, {'surname': 'Иванов', 'firstname': 'Саша', 'salary': 5100}, {'surname': 'Сидоров', 'firstname': 'Андрей', 'salary': 12345}]
>>>

Разделение по всем полям
  
>>> import re
>>> 
>>> def split1(s):
...     parts = re.findall(r'^(\S+)\s*(.*)\s+(\S+)\s+(\d+)$', s)[0]
...     out = {'surname': parts[0],
...            'firstname': parts[2],
...            'status': parts[1] or None,
...            'salary': int(parts[3])}
...     return out
... 
>>> 
>>> lst = ['Петров Герой труда Петр 100000',
...        'Иванов Саша 5100',
...        'Сидоров Старик Андрей 12345']
>>> 
>>> out = list(map(split1, lst))
>>> out
[{'surname': 'Петров', 'firstname': 'Петр', 'status': 'Герой труда', 'salary': 100000}, {'surname': 'Иванов', 'firstname': 'Саша', 'status': None, 'salary': 5100}, {'surname': 'Сидоров', 'firstname': 'Андрей', 'status': 'Старик', 'salary': 12345}]
>>>
SomethingButNotNickName
насколько я понял предлагается такой алгоритм:
1) сортировка одного из файлов, чтобы конкретному человеку соответствовала строка под одинаковым номером в обоих файлах, т.е. мы перезаписываем один из файлов;
2) в цикле:
а) взять строку первого файла;
б) взять строку второго файла;
в) слепить из них класс, описать в этом классе метод подсчета заработка;
г) запустить метод подсчета заработка и вывести результат.
Таким образом, мы пробежим по обоим файлам и после прочтения строки будем выдавать результат.
И в памяти не будут лежать не нужные словари по сотрудникам, которые ожидают расчета или уже рассчитаны.

Все верно?

и еще вопрос по регулярке
 parts = re.findall(r'^(\S+).*\s(\S+)\s+(\d+)$', s)[0]
$ - указатель на конец строки, т.е. если после цифр будет что-то еще паттерн не должен сработать. А для чего эта проверка?


marvellik
py.user.next а не проще создать словарь где ключ это имя фамилия ну а значение зарплата?
мне кажется меньше путаницы будет
py.user.next
marvellik
py.user.next а не проще создать словарь где ключ это имя фамилия ну а значение зарплата?
К одному человеку относится куча всяких значений. Поэтому для одного человека делается один словарь и все данные в нём относятся только к этому человеку. А полей там может быть сотня.

marvellik
мне кажется меньше путаницы будет
Путаница тут возникает только оттого, что SomethingButNotNickName думает, что может сам что-то сделать. Ему говорят “делай словари”, а он такой “нет, мне вот словари не нужны, мне сказали классы какие-то там делать”. Ему опять говорят “делай словари”, а он опять повторяет то же самое. Вот это путаница.

SomethingButNotNickName
1) сортировка одного из файлов, чтобы конкретному человеку соответствовала строка под одинаковым номером в обоих файлах, т.е. мы перезаписываем один из файлов;
А если там будет разное количество людей?
А если там будет миллион людей ещё к тому же?
То есть ты будешь затратно сортировать, а смысла в этом не будет никакого. Ты не контролируешь содержимое этих файлов. Откуда оно приходит и кого туда могут добавить? - это всё от тебя не зависит.

SomethingButNotNickName
а) взять строку первого файла;
б) взять строку второго файла;
И первая строка - один человек, а другая строка - другой человек. (Это ты отсортировал файлы, в которых есть разные люди, но ты про это не знал.)
Как ты, вообще, прогарантировал то, что даже просто люди одни и те же в этих файлах? С чего ты взял, что эти файлы образуют биективное отображение? Может, в первом файле есть человек, которого нет во втором файле, а во втором файле есть человек, которого нет в первом файле? Да, они могут пересекаться, но пересечение ещё не гарантирует, что эти файлы отображаются один человек в один человек в обе стороны. В задании это нигде не написано.

И в реале обычно так и устроены базы данных: есть просто разные таблицы, где есть одинаковые элементы (люди, товары и прочее), в каждой таблице свои какие-то данные про эти элементы; но из того, что эти данные есть в обеих таблицах, не следует, что эти таблицы связаны друг с другом. Одну таблицу может одна хрень какая-нибудь заполнять, а другую таблицу может другая хрень заполнять. И первая хрень не будет смотреть во вторую таблицу, а вторая хрень не будет смотреть в первую таблицу. Они про них не знают, они только за свои таблицы отвечают.

SomethingButNotNickName
$ - указатель на конец строки, т.е. если после цифр будет что-то еще паттерн не должен сработать. А для чего эта проверка?
Оно может совпасть с чем-нибудь в середине. Ты никак не контролиуешь то, что в середине не может быть цифр. Например “фамилия ударник завода номер 123 имя зарплата”. Вот чтобы оно в середине ни с чем не совпало, ты говоришь ему “ищи в конце цифры и бери от них первое слово слева”.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB