【问题标题】:Split dictionary field拆分字典字段
【发布时间】:2017-02-14 22:29:29
【问题描述】:

我已经设法弄清楚如何运行 SQL 查询来显示信息。我需要将数据保持与 db 表相同的形式,所以我认为我应该使用字典。到目前为止,我的字段是 ID 和 Name,我的打印如下所示:

[{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}, ...]

首先,我是否恰当地使用了字典?

接下来,我需要根据* 分隔符拆分名称字段。例如:

之前:

{'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'} 

之后:

{'ID': '789', 'LastName': 'KRISTENSEN', 'FirstName': 'KRISTEN'}

我已经测试了一些我发现的代码,但一直遇到障碍。我用它来创建我的字典,我想知道我是否在这一行中包含一个拆分以减少一个步骤?

query = [dict(zip(['ID', 'Name'],row)) for row in cursor.fetchall()]

【问题讨论】:

  • 可能对您没有帮助,但如果可能的话,我觉得最好的方法是将您的数据库更改为具有 LastName 和 FirstName 字段。
  • 如果它只是那么简单@bouletta :-)

标签: python sql-server dictionary split


【解决方案1】:

也许是这样:

query = [dict(zip(['ID', 'FirstName', 'LastName'], row[:1] + row[1].split('*'))) for row in cursor.fetchall()]

【讨论】:

  • TypeError: can only concatenate tuple (not "list") to tuple
【解决方案2】:
db_dict = {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}
name = db_dict['Name']

def split_name(name):
    for index, char in enumerate(name):
        if char == '*':
            position = index

    last_name = name[:position]
    first_name = name[position + 1:]

    return {'LastName':last_name, 'FirstName':first_name}

new_db_dict = {db_dict.keys()[0] : db_dict.values()[0]}
new_db_dict.update(split_name(name))
print new_db_dict

【讨论】:

  • TypeError: list indices must be integers or slices, not str
  • 我可以执行这段代码而不会出现任何错误:/
  • 也许是因为其中一些没有星号?有什么办法吗?
【解决方案3】:

首先,虽然您对字典的使用是有效的,但我建议使用 namedtuples 来表示具有命名字段的固定结构

   from collections import namedtuple
   # structure class factory
   Person = namedtuple("Person", ("id", "name"))
   people = [ Person('123', 'ROBERTSON*ROBERT'), Person('456','MICHAELS*MIKE'), Person('789', 'KRISTENSEN*KRISTEN')]
   # different structure
   PersonName = namedtuple("Person", ("id", "first", "last"))
   # structure transformation
   def person_to_personname(person):
       """Transform Person -> PersonName"""
       names = person.name.split('*')
       if len(names) < 2:  # depends on your defaults
            last = names[0]
            first = ''
       else:  # assumes first field is last name
            last, first = names[:2]  # even if other names present, takes first two
       return PersonName(person.id, first, last)
   people_names = [person_to_personname(person) for person in people]

【讨论】:

    【解决方案4】:

    如果所有条目的名称都用星号分隔

    分两步解决。检索到当前结果后:

    a = [{'ID': '123', 'Name': 'ROBERTSON*ROBERT'}, {'ID': '456', 'Name': 'MICHAELS*MIKE'}, {'ID': '789', 'Name': 'KRISTENSEN*KRISTEN'}] 
    
    result = [{'ID' : entry['ID'], 'LastName' : entry['Name'].split('*')[0], 'FirstName' : entry['Name'].split('*')[1]} for entry in a]
    

    现在如果你打印结果:

    [{'FirstName': 'ROBERT', 'ID': '123', 'LastName': 'ROBERTSON'},
     {'FirstName': 'MIKE', 'ID': '456', 'LastName': 'MICHAELS'},
     {'FirstName': 'KRISTEN', 'ID': '789', 'LastName': 'KRISTENSEN'}]
    

    否则(假设至少填充了“姓名”字段)

    results = []
    
    for entry in a:
        name = entry['Name'].split('*')
    
        result = dict(ID = entry['ID'], LastName = name[0])
    
        if len(name) > 1:
            result['FirstName'] = name[1]
    
        results.append(result)
    

    【讨论】:

    • IndexError: list index out of range
    • 它适用于我的示例,如果您的一个条目没有由 * 分隔的名字/姓氏,它将失败
    • 总有办法解决:)。但是你希望这个案子怎么处理?只有姓氏,没有任何内容存储在 FirstName 中?
    • 我编辑了我的答案,它的行为与以前一样,在没有* 的情况下,全名将存储在姓氏中,名字将不存在。如果您希望它存在,那么您可以添加一个elsestatement 并在其中放入一个空字符串。您也可以使用 try except 语句代替 if/else,但这可能有点矫枉过正。
    • 谢谢@bouletta。这很好用!没有错误,但我只打印了一条记录{'ID': '123', 'LastName': 'SMITH', 'FirstName': 'ROBERT'}
    猜你喜欢
    • 1970-01-01
    • 2021-09-09
    • 2021-11-17
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 2021-12-09
    相关资源
    最近更新 更多