Проверка членства внутри вложенного dict

Это следующие вопросы к этому:

Python DictReader – Пропуск строк с отсутствующими столбцами?

Оказывается, я был глупым и использовал неправильное поле ID.

Я использую Python 3.x здесь, кстати.

У меня есть указатель сотрудников, индексированный строкой, «directory_id». Каждое значение представляет собой вложенный dict с атрибутами сотрудника (номер телефона, фамилия и т. Д.). Одним из этих значений является вторичный идентификатор, например «internal_id», а другой – его менеджер, назовите его «manager_internal_id». Поле «internal_id» необязательно, и не каждый сотрудник имеет его.

{'6443410501': {'manager_internal_id': '989634', 'givenName': 'Mary', 'phoneNumber': '+65 3434 3434', 'sn': 'Jones', 'internal_id': '434214'} '8117062158': {'manager_internal_id': '180682', 'givenName': 'John', 'phoneNumber': '+65 3434 3434', 'sn': 'Ashmore', 'internal_id': ''} '9227629067': {'manager_internal_id': '347394', 'givenName': 'Wright', 'phoneNumber': '+65 3434 3434', 'sn': 'Earl', 'internal_id': '257839'} '1724696976': {'manager_internal_id': '907239', 'givenName': 'Jane', 'phoneNumber': '+65 3434 3434', 'sn': 'Bronte', 'internal_id': '629067'} 

}

(Я немного упростил поля, как для упрощения чтения, так и для соображений конфиденциальности / соблюдения).

Проблема здесь в том, что мы индексируем (ключе) каждого сотрудника по их каталогу_id, но когда мы ищем своего менеджера, нам нужно найти менеджеров по их «internal_id».

Раньше, когда наш dict использовал internal_id в качестве ключа, employee.keys () был списком internal_ids, и я использовал проверку членства на этом. Теперь последняя часть моего оператора if не будет работать, поскольку internal_ids является частью значений dict, а не самого ключа.

 def lookup_supervisor(manager_internal_id, employees): if manager_internal_id is not None and manager_internal_id != "" and manager_internal_id in employees.keys(): return (employees[manager_internal_id]['mail'], employees[manager_internal_id]['givenName'], employees[manager_internal_id]['sn']) else: return ('Supervisor Not Found', 'Supervisor Not Found', 'Supervisor Not Found') 

Итак, первый вопрос: как я могу исправить оператор if, чтобы проверить, присутствует ли manager_internal_id в списке dict_id dict?

Я попытался заменить employee.keys () на employee.values ​​(), который не работал. Кроме того, я надеюсь на что-то более эффективное, не уверен, есть ли способ получить подмножество значений, в частности, все записи для сотрудников [directory_id] ['internal_id'].

Надеюсь, есть какой-то Pythonic способ сделать это, не используя массивную кучу вложенных для / if циклов.

Мой второй вопрос: как я могу чисто вернуть требуемые атрибуты сотрудника (почта, имя, фамилия и т. Д.). Цикл «Мой цикл» выполняет итерацию над каждым сотрудником и вызывает lookup_supervisor. Я чувствую себя немного глупо / тупо.

 def tidy_data(employees): for directory_id, data in employees.items(): # We really shouldnt' be passing employees back and forth like this - hmm, classes? data['SupervisorEmail'], data['SupervisorFirstName'], data['SupervisorSurname'] = lookup_supervisor(data['manager_internal_id'], employees) 

Должен ли я перепроектировать мою структуру данных? Или есть другой способ?

EDIT: Я немного изменил код, см. Ниже:

 class Employees: def import_gd_dump(self, input_file="test.csv"): gd_extract = csv.DictReader(open(input_file), dialect='excel') self.employees = {row['directory_id']:row for row in gd_extract} def write_gd_formatted(self, output_file="gd_formatted.csv"): gd_output_fieldnames = ('internal_id', 'mail', 'givenName', 'sn', 'dbcostcenter', 'directory_id', 'manager_internal_id', 'PHFull', 'PHFull_message', 'SupervisorEmail', 'SupervisorFirstName', 'SupervisorSurname') try: gd_formatted = csv.DictWriter(open(output_file, 'w', newline=''), fieldnames=gd_output_fieldnames, extrasaction='ignore', dialect='excel') except IOError: print('Unable to open file, IO error (Is it locked?)') sys.exit(1) headers = {n:n for n in gd_output_fieldnames} gd_formatted.writerow(headers) for internal_id, data in self.employees.items(): gd_formatted.writerow(data) def tidy_data(self): for directory_id, data in self.employees.items(): data['PHFull'], data['PHFull_message'] = self.clean_phone_number(data['telephoneNumber']) data['SupervisorEmail'], data['SupervisorFirstName'], data['SupervisorSurname'] = self.lookup_supervisor(data['manager_internal_id']) def clean_phone_number(self, original_telephone_number): standard_format = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') extra_zero = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') missing_hyphen = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})(?P<local_second_half>\d{4})') if standard_format.search(original_telephone_number): result = standard_format.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), '' elif extra_zero.search(original_telephone_number): result = extra_zero.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Extra zero in area code - ask user to remediate. ' elif missing_hyphen.search(original_telephone_number): result = missing_hyphen.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Missing hyphen in local component - ask user to remediate. ' else: return '', "Number didn't match format. Original text is: " + original_telephone_number def lookup_supervisor(self, manager_internal_id): if manager_internal_id is not None and manager_internal_id != "":# and manager_internal_id in self.employees.values(): return (employees[manager_internal_id]['mail'], employees[manager_internal_id]['givenName'], employees[manager_internal_id]['sn']) else: return ('Supervisor Not Found', 'Supervisor Not Found', 'Supervisor Not Found') if __name__ == '__main__': our_employees = Employees() our_employees.import_gd_dump('test.csv') our_employees.tidy_data() our_employees.write_gd_formatted() & class Employees: def import_gd_dump(self, input_file="test.csv"): gd_extract = csv.DictReader(open(input_file), dialect='excel') self.employees = {row['directory_id']:row for row in gd_extract} def write_gd_formatted(self, output_file="gd_formatted.csv"): gd_output_fieldnames = ('internal_id', 'mail', 'givenName', 'sn', 'dbcostcenter', 'directory_id', 'manager_internal_id', 'PHFull', 'PHFull_message', 'SupervisorEmail', 'SupervisorFirstName', 'SupervisorSurname') try: gd_formatted = csv.DictWriter(open(output_file, 'w', newline=''), fieldnames=gd_output_fieldnames, extrasaction='ignore', dialect='excel') except IOError: print('Unable to open file, IO error (Is it locked?)') sys.exit(1) headers = {n:n for n in gd_output_fieldnames} gd_formatted.writerow(headers) for internal_id, data in self.employees.items(): gd_formatted.writerow(data) def tidy_data(self): for directory_id, data in self.employees.items(): data['PHFull'], data['PHFull_message'] = self.clean_phone_number(data['telephoneNumber']) data['SupervisorEmail'], data['SupervisorFirstName'], data['SupervisorSurname'] = self.lookup_supervisor(data['manager_internal_id']) def clean_phone_number(self, original_telephone_number): standard_format = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') extra_zero = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') missing_hyphen = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})(?P<local_second_half>\d{4})') if standard_format.search(original_telephone_number): result = standard_format.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), '' elif extra_zero.search(original_telephone_number): result = extra_zero.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Extra zero in area code - ask user to remediate. ' elif missing_hyphen.search(original_telephone_number): result = missing_hyphen.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Missing hyphen in local component - ask user to remediate. ' else: return '', "Number didn't match format. Original text is: " + original_telephone_number def lookup_supervisor(self, manager_internal_id): if manager_internal_id is not None and manager_internal_id != "":# and manager_internal_id in self.employees.values(): return (employees[manager_internal_id]['mail'], employees[manager_internal_id]['givenName'], employees[manager_internal_id]['sn']) else: return ('Supervisor Not Found', 'Supervisor Not Found', 'Supervisor Not Found') if __name__ == '__main__': our_employees = Employees() our_employees.import_gd_dump('test.csv') our_employees.tidy_data() our_employees.write_gd_formatted() ; class Employees: def import_gd_dump(self, input_file="test.csv"): gd_extract = csv.DictReader(open(input_file), dialect='excel') self.employees = {row['directory_id']:row for row in gd_extract} def write_gd_formatted(self, output_file="gd_formatted.csv"): gd_output_fieldnames = ('internal_id', 'mail', 'givenName', 'sn', 'dbcostcenter', 'directory_id', 'manager_internal_id', 'PHFull', 'PHFull_message', 'SupervisorEmail', 'SupervisorFirstName', 'SupervisorSurname') try: gd_formatted = csv.DictWriter(open(output_file, 'w', newline=''), fieldnames=gd_output_fieldnames, extrasaction='ignore', dialect='excel') except IOError: print('Unable to open file, IO error (Is it locked?)') sys.exit(1) headers = {n:n for n in gd_output_fieldnames} gd_formatted.writerow(headers) for internal_id, data in self.employees.items(): gd_formatted.writerow(data) def tidy_data(self): for directory_id, data in self.employees.items(): data['PHFull'], data['PHFull_message'] = self.clean_phone_number(data['telephoneNumber']) data['SupervisorEmail'], data['SupervisorFirstName'], data['SupervisorSurname'] = self.lookup_supervisor(data['manager_internal_id']) def clean_phone_number(self, original_telephone_number): standard_format = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') extra_zero = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})-(?P<local_second_half>\d{4})') missing_hyphen = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{4})(?P<local_second_half>\d{4})') if standard_format.search(original_telephone_number): result = standard_format.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), '' elif extra_zero.search(original_telephone_number): result = extra_zero.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Extra zero in area code - ask user to remediate. ' elif missing_hyphen.search(original_telephone_number): result = missing_hyphen.search(original_telephone_number) return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), 'Missing hyphen in local component - ask user to remediate. ' else: return '', "Number didn't match format. Original text is: " + original_telephone_number def lookup_supervisor(self, manager_internal_id): if manager_internal_id is not None and manager_internal_id != "":# and manager_internal_id in self.employees.values(): return (employees[manager_internal_id]['mail'], employees[manager_internal_id]['givenName'], employees[manager_internal_id]['sn']) else: return ('Supervisor Not Found', 'Supervisor Not Found', 'Supervisor Not Found') if __name__ == '__main__': our_employees = Employees() our_employees.import_gd_dump('test.csv') our_employees.tidy_data() our_employees.write_gd_formatted() 

Я предполагаю (1). Я ищу лучший способ структурирования / хранения Employee / Employees и (2) У меня возникают проблемы, в частности с lookup_supervisor (). \

Должен ли я создавать класс Employee и встраивать их внутри Employees?

И должен ли я делать то, что я делаю с tidy_data (), и вызывать clean_phone_number () и lookup_supervisor () в цикле for на элементах dict? Urgh. смущен .

  • Подсчет частоты каждой буквы в строке
  • как разбирать строку в словаре
  • Вычислить разницу в ключах, содержащихся в двух словарях Python
  • Ссылка на словарь Python на соседний словарь
  • Добавить новые ключи в словарь?
  • Как правильно подклассировать dict и переопределить __getitem__ & __setitem__
  • Сортировка словаря (с ключами даты) в Python
  • Python: проверка того, что «словарь» пуст, кажется, не работает
  • 2 Solutions collect form web for “Проверка членства внутри вложенного dict”

    Мои навыки питона слабы, поэтому я слишком неосведомлен, чтобы выписать то, что я имею в виду в любое разумное время. Но я знаю, как делать декомпозицию OO.

    Почему класс Employees выполняет всю работу? Есть несколько типов вещей, которые делает ваш класс монолитных сотрудников:

    • Чтение и запись данных из файла – aka serialization
    • Управление и доступ к данным от отдельных сотрудников
    • Управление отношениями между внешними работниками.

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

    Определите класс Employee для отслеживания или данных сотрудников и обработки задач обработки / очистки.

    Используйте класс Employees как контейнер для объектов-сотрудников. Он может обрабатывать такие задачи, как отслеживание надзора сотрудника.

    Определите виртуальный базовый класс EmployeeLoader для определения интерфейса (load, store,?). Затем выполните подкласс для сериализации файлов CSV. (Виртуальный базовый класс является необязательным – я не уверен, как Python обрабатывает виртуальные классы, поэтому это может даже не иметь смысла.)

    Так:

    • создайте экземпляр EmployeeCSVLoader с именем файла для работы.
    • Затем загрузчик может создать объект Employees и проанализировать файл.
    • По мере чтения каждой записи создается новый объект Employee и сохраняется в объекте Employees.
    • Теперь попросите объект Employees заполнить ссылки супервизора.
    • Итерации над коллекцией сотрудников сотрудников и попросите каждого привести себя в порядок.
    • Наконец, пусть объект сериализации обрабатывает файл данных.

    Почему этот проект стоит усилий?

    Это облегчает понимание. Меньшие задачи, ориентированные на задачи, легче создавать чистые, совместимые API.

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

    В общем, используйте объекты для упрощения и структурирования ваших данных. Отделите общие данные и поведение на отдельные классы. Держите каждый класс плотно сосредоточенным на одном типе способностей. Если ваш класс представляет собой коллекцию, аксессуар, фабрику, кухонную раковину, API никогда не может быть использован: он будет слишком большим и загружен разными группами методов. Но если ваши занятия останутся на тему, они будут легко тестироваться, поддерживать, использовать, повторно использовать и распространять.

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

    Попробуйте это для размера:

     def lookup_supervisor(manager_internal_id, employees): if manager_internal_id is not None and manager_internal_id != "": manager_dir_ids = [dir_id for dir_id in employees if employees[dir_id].get('internal_id') == manager_internal_id] assert(len(manager_dir_ids) <= 1) if len(manager_dir_ids) == 1: return manager_dir_ids[0] return None def tidy_data(employees): for emp_data in employees.values(): manager_dir_id = lookup_supervisor(emp_data.get('manager_internal_id'), employees) for (field, sup_key) in [('Email', 'mail'), ('FirstName', 'givenName'), ('Surname', 'sn')]: emp_data['Supervisor'+field] = (employees[manager_dir_id][sup_key] if manager_dir_id is not None else 'Supervisor Not Found') 

    И вы определенно правы, что класс – это ответ на прохождение employees . На самом деле, я бы рекомендовал не хранить ключи «Супервизора» у сотрудника dict и предлагать вместо этого получать супервизор, если он нужен вам, возможно, с помощью метода get_supervisor_data .

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

     def clean_phone_number(self, original_telephone_number): phone_re = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<extra_zero>0?)(?P<area_code>\d)\)(?P<local_first_half>\d{4})(?P<hyph>-?)(?P<local_second_half>\d{4})') result = phone_re.search(original_telephone_number) if result is None: return '', "Number didn't match format. Original text is: " + original_telephone_number msg = '' if result.group('extra_zero'): msg += 'Extra zero in area code - ask user to remediate. ' if result.group('hyph'): # Note: can have both errors at once msg += 'Missing hyphen in local component - ask user to remediate. ' return '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half'), msg 

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

    Python - лучший язык программирования в мире.