Python 检查嵌套dict中的成员身份

Python 检查嵌套dict中的成员身份,python,dictionary,Python,Dictionary,以下是这一问题的后续问题: 结果证明我很傻,使用了错误的ID字段 顺便说一句,我在这里使用的是Python3.x 我有一份员工的口述,由一个字符串“directory\u id”索引。每个值都是带有员工属性(电话号码、姓氏等)的嵌套dict。其中一个值是辅助ID,称为“内部ID”,另一个值是它们的管理器,称之为“管理器内部ID”。“internal_id”字段是非必填字段,并非每个员工都有一个 {'6443410501': {'manager_internal_id': '989634', '

以下是这一问题的后续问题:

结果证明我很傻,使用了错误的ID字段

顺便说一句,我在这里使用的是Python3.x

我有一份员工的口述,由一个字符串“directory\u id”索引。每个值都是带有员工属性(电话号码、姓氏等)的嵌套dict。其中一个值是辅助ID,称为“内部ID”,另一个值是它们的管理器,称之为“管理器内部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索引(键)每个员工,但当我们查找他们的经理时,我们需要通过他们的“内部id”查找经理

以前,当我们的dict使用internal_id作为键时,employee.keys()是一个internal_id列表,我使用了一个成员资格检查。现在,if语句的最后一部分不起作用,因为内部_id是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\u internal\u id是否存在于dict的internal\u id列表中

我尝试用employee.values()替换employee.keys(),但没有成功。另外,我希望有更有效的方法,不确定是否有办法获得值的子集,特别是员工的所有条目[directory_id]['internal_id']

希望有一些python的方法可以做到这一点,而不需要使用大量嵌套的for/if循环

我的第二个问题是,如何干净地返回所需的员工属性(邮件、givenname、姓氏等)。我的for循环迭代每个员工,并调用lookup\u主管。我在这里感到有点愚蠢/难堪

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)
我应该重新设计我的数据结构吗?还是有别的办法

编辑:我稍微调整了代码,请参见以下内容:

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员工:
def导入\u gd_转储(自,输入文件=“test.csv”):
gd_extract=csv.DictReader(打开(输入文件),方言='excel')
self.employees={row['directory\u id']:gd\u extract中的行对应行}
def write_gd_formatted(self,output_file=“gd_formatted.csv”):
gd_输出_字段名=('internal_id'、'mail'、'givenName'、'sn'、'dbcostcenter'、'directory_id'、'manager_internal_id'、'PHFull'、'PHFull_message'、'SupervisorEmail'、'SupervisorFirstName'、'supervisorUrName')
尝试:
gd_formatted=csv.DictWriter(打开(输出文件'w',换行符=''),字段名=gd_输出字段名,extraction='ignore',方言='excel')
除IOError外:
打印('无法打开文件,IO错误(是否已锁定?))
系统出口(1)
headers={n:n表示gd_output_fieldnames中的n}
gd_格式化的.writerow(标题)
对于内部id,self.employees.items()中的数据:
gd_格式化的.writerow(数据)
def TIDIY_数据(自身):
对于目录_id,self.employees.items()中的数据:
数据['PHFull'],数据['PHFull_message']=self.clean_电话号码(数据['telephoneNumber'])
数据['SupervisorEmail']、数据['SupervisorFirstName']、数据['SupervisorUrName']=self.lookup\u主管(数据['manager\u internal\u id'])
def清洁电话号码(自身、原始电话号码):
标准格式=重新编译(r'^\+(?P\d{2})\(?P\d)\(?P\d{4})-(?P\d{4}))
额外零=重新编译(r'^\+(?P\d{2})\(0(?P\d)\(?P\d{4})-(?P\d{4}))
缺少重新编译(r'^\+(?P\d{2})\(0(?P\d)\)(?P\d{4})(?P\d{4}))
如果是标准格式搜索(原始电话号码):
结果=标准格式。搜索(原始电话号码)
返回“0”+result.group('area_code')+result.group('local_first_half')+result.group('local_second_half'),“”
elif额外零搜索(原始电话号码):
结果=额外零。搜索(原始电话号码)
返回“0”+result.group('area_code')+result.group('local_first_half')+result.group('local_second_half'),“区号中的额外零-请用户进行修正。”
elif缺少连字符搜索(原始电话号码):
结果=缺少连字符搜索(原始电话号码)
返回“0”+result.group('area_code')+result.group('local_first_half')+result.group('local_second_half'),“本地组件中缺少连字符-请用户进行修正。”
其他:
返回“”,“号码与格式不匹配。原始文本为:“+原始电话号码”
def查找\u主管(自我、经理\u内部\u id):
如果manager\u internal\u id不是None且manager\u internal\u id!=“”:#和self.employees.values()中的经理_internal_id:
返回(员工[经理内部身份证]['mail']、员工[经理内部身份证]['givenName']、员工[经理内部身份证]['sn'])
其他:
返回(‘找不到主管’、‘找不到主管’、‘找不到主管’)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
我们的员工=员工()
我们的员工。导入\u gd\u转储('test.csv')
我们的员工。整理数据()
我们的员工。编写
我猜(1)。我正在寻找一种更好的方法来组织/存储员工,并且(2)我特别在查找\ U主管()方面遇到了问题\

我应该创建一个Employee类,并将这些类嵌套在Employee内部吗


我是否应该像处理tidy_data()一样,在dict的项目上的for循环中调用clean_phone_number()和lookup_supervisor()?呃。困惑。

您可能需要进行一些迭代才能获得数据。我想你不需要一个额外的dict,它可能会过时,所以尝试存储内部id上键入的所有内容是不值得的

试试这个尺码:

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')
你当然可以为每个员工制作一个单独的对象,但是看看你是如何
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