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

Позвольте мне в предисловии сказать, что я не уверен на 100%, является ли использование словаря лучшим способом действий для этой задачи, но я считаю, что это то, что мне нужно использовать для выполнения этой задачи.

У меня есть файл .txt, отформатированный следующим образом:

first_name last_name rate hours
first_name last_name rate hours
first_name last_name rate hours
first_name last_name rate hours

Между каждым элементом есть один пробел. Каждая линия представляет человека.

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

  • распечатать всех людей сразу
  • иметь возможность искать человека по имени или фамилии и распечатывать его информацию
  • изменить человека (имя, фамилия, часы работы, скорость)
  • удалить человека (всю его информацию)

Когда он будет напечатан, мне НЕ нужно видеть [ставка] и [часы], а вместо этого [брутто-зарплата] (брутто-зарплата = ставка * часы).

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

# 'print_emp', display only a single employee's data chosen by the user displayed as
# firstname, lastname, grosspay (on one line of output)
def print_emp():
    menu_name = ' '*int(OFFSET/2) + "EMPLOYEE LOOKUP"
    dotted = (OFFSET+len(menu_name))*'-'

    try:
        with open('employees.txt') as file:
            print('{} \n{} \n{}'.format(dotted, menu_name, dotted))
            emp_name = input("Employee Name: ")
            print('{0:20} {1:20} {2}'.format("First Name", "Last Name", "Gross Pay"))
            for line in file:
                if emp_name in line:
                    print (line.strip())

                #print("\nEmployee", emp_name, "does not exist. Try again.\n")
                #break
    except FileNotFoundError:
        print("Error: File not found.")


# 'print_all_emp', display all employee data in format firstname, lastname,
# grosspay (on one line of output per employee)
def print_all_emps():
    menu_name = ' '*int(OFFSET/2) + "EMPLOYEE LIST"
    dotted = (OFFSET+len(menu_name))*'-'

    try:
        with open('employees.txt', 'r') as file:
            print('{} \n{} \n{}'.format(dotted, menu_name, dotted))
            print('{0:20} {1:20} {2}'.format("First Name", "Last Name", "Gross Pay"))
            for line in file:
                print(line.strip())
            print(dotted)
    except FileNotFoundError:
        print("Error: File not found.")

Я не уверен, как мне читать мой .txt файл в словарь (если это то, что мне нужно сделать), где я назначаю каждому человеку ключ, который включает их имя, фамилию, скорость и часы, а затем умножаю rate * hours для создания брутто-зарплаты, а затем отображения этой брутто-зарплаты.

Я создам еще три функции, в которых я смогу добавлять, удалять и изменять людей в файле .txt.

ИЗМЕНИТЬ:

Я считаю, что то, что я собираюсь сделать в качестве конечной программы, выглядит примерно так:

https://en.wikibooks.org/wiki/Непрограммист%27s_Tutorial_for_Python_3/File_IO

Но без функций загрузки и сохранения...


person ByteSettlement    schedule 06.07.2016    source источник
comment
Несколько не связано с вашим вопросом, но как вы планируете обрабатывать имена, в которых есть пробел?   -  person spectras    schedule 07.07.2016
comment
@spectras Это не входило в рамки моего проекта, поэтому я не думал об этом. Давайте просто предположим, что мой проект будет использовать только типичные имена и фамилии, такие как Джон Смит.   -  person ByteSettlement    schedule 07.07.2016
comment
глупый вопрос, а в вашем файле действительно есть скобки, или вы просто используете их, чтобы сделать формат понятным?   -  person Hans Nelsen    schedule 07.07.2016
comment
Почему вы не используете панд? Просто замените свой файл файлом csv (например, замените скобки кавычками, а пробел запятой), прочитайте его с помощью pandas, и у вас будет все, что вам нужно, всего несколькими строками.   -  person CentAu    schedule 07.07.2016
comment
@HansNelsen скобки используются только для форматирования, на самом деле в файле нет скобок   -  person ByteSettlement    schedule 07.07.2016


Ответы (4)


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

import csv

labels = ['first_name', 'last_name', 'rate', 'hours']
data = csv.DictReader(open('./test.txt'), delimiter=' ', fieldnames=labels)

result = []

for row in data:
  result.append(row)

print result

Вы получите массив словарей, каждый из которых имеет метки в качестве имен ключей.

person Hans Nelsen    schedule 06.07.2016
comment
это конвертирует мой файл в файл csv? Мне нужно, чтобы файл выглядел так, как сейчас, в формате txt. - person ByteSettlement; 07.07.2016
comment
@ByteSettlement Нет, когда вы читаете файл, вы указываете разделитель в виде пробела. - person arewm; 07.07.2016

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

res = {}
with open('employees.txt') as file:
   for line in file:
       res[line] = line.split(' ')
person galaxyan    schedule 06.07.2016

Вы несколько упрощаете код, создавая класс Person.

class Person:
    def __init__(self, first, last, rate, hours):
       self.first = first
       self.last = last
       self.rate = rate
       self.hours = hours

    def matches_name(self, name):
        return name.lower() == self.first.lower() or name.lower() == self.last.lower()

    def __str__(self):
        return '{} {} {}'.format(self.first, self.last, self.rate*self.hours)

Это немного упростит ваш код. Если вы хотите узнать, есть ли у кого-то конкретное имя, вы можете просто вызвать что-то вроде:

a_person.matches_name(random_first_name)

Если вы хотите распечатать человека и его валовую зарплату, вам просто нужно сделать

print(a_person)
person arewm    schedule 06.07.2016
comment
Для упрощения классы — это способ хранить информацию, относящуюся к конкретной вещи, вместе. Здесь вы хотите описать человека, поэтому создайте класс Person. В этом классе вы можете хранить информацию о любом человеке и использовать методы класса для выполнения простых операций, таких как «Я такой же человек, как и другой?», «Как меня зовут?» и «Что такое простое резюме самого себя?». - person arewm; 07.07.2016
comment
Они очень полезны, поэтому я надеюсь, что при изучении Python вы узнаете о них больше. :) - person arewm; 07.07.2016

Вы можете легко выполнить все желаемые операции с помощью pandas:

>>> import pandas as pd

Сначала преобразуйте файл в формат csv (текстовый файл с разделителями-запятыми), затем:

предполагая, что ваш файл находится в txt:

>>> txt = """                
    'FN','LN','rate','hours'
    'John','Doe','12','40'
    'Jane','Roe','20','35'
    """

>>> file = StringIO(txt)

>>> df = pd.read_csv(file, quotechar="'")

>>> df
Out: 
     FN   LN  rate  hours
0  John  Doe    12     40
1  Jane  Roe    20     35

распечатать всех людей сразу:

>>> df[['FN','LN']]
Out: 
     FN   LN
0  John  Doe
1  Jane  Roe

Найдите человека по имени или фамилии и распечатайте информацию о нем:

>>> df.loc[df['FN'] == 'John']
Out: 
     FN   LN  rate  hours
0  John  Doe    12     40

>>> df.loc[df['LN'] == 'Roe']
Out: 
     FN   LN  rate  hours
1  Jane  Roe    20     35

Изменить человека (имя, фамилия, часы работы, тариф):

Я покажу изменение ставки для человека по имени «Джон».

>>> df.loc[df['FN'] == 'John', 'rate'] = 14

>>> df
Out: 
     FN   LN  rate  hours
0  John  Doe    14     40
1  Jane  Roe    20     35

Удалить человека (всю его информацию):

Я покажу удаление «John Doe»:

>>> df = df[(df['FN'] != 'John') & (df['LN'] != 'Doe')]

>>> df
Out: 
     FN   LN  rate  hours
1  Jane  Roe    20     35

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

>>> values = df['rate'] * df['hours']

>>> df['pay'] = values

>>> df
Out[67]: 
     FN   LN  rate  hours  pay
0  John  Doe    12     40  480
1  Jane  Roe    20     35  700
person CentAu    schedule 06.07.2016