2017-02-01 20 views
1

我想将字典转换为字符串。是什么初学者级别的问题是,我必须坚持一些规则复杂:以任意顺序处理字典密钥

  • 存在必须在特定的问世已知密钥列表,任意顺序
  • 每个已知键是可选,即它可能不存在于字典中
  • 保证至少一个已知密钥将出现在字典中
  • 字典可能包含额外的密钥;他们一定要来认识的按键及它们的顺序并不重要
  • 我不能对顺序键将被添加到字典

什么是别人之前处理一些字典键的Python的方式假设?

到目前为止,我有以下功能:

def format_data(input_data): 
    data = dict(input_data) 
    output = [] 
    for key in ["title", "slug", "date", "modified", "category", "tags"]: 
     if key in data: 
      output.append("{}: {}".format(key.title(), data[key])) 
      del data[key] 

    if data: 
     for key in data: 
      output.append("{}: {}".format(key.title(), data[key])) 

    return "\n".join(output) 
data = { 
    "tags": "one, two", 
    "slug": "post-title", 
    "date": "2017-02-01", 
    "title": "Post Title", 
} 

print(format_data(data)) 

data = { 
    "format": "book", 
    "title": "Another Post Title", 
    "date": "2017-02-01", 
    "slug": "another-post-title", 
    "custom": "data", 
} 

print(format_data(data)) 

Title: Post Title 
Slug: post-title 
Date: 2017-02-01 
Tags: one, two 

Title: Another Post Title 
Slug: another-post-title 
Date: 2017-02-01 
Custom: data 
Format: book 

虽然这个功能确实提供了预期的结果,它有一些问题,让我觉得有可能是更好的方法。即,output.append()行被复制并且输入数据结构被复制以允许其修改而没有副作用。

综上所述,我怎么可以处理特定的顺序和之前其他一些按键按键?

+1

我没有看到你的实现有什么特别的错误。 '如果数据:'是不必要的,但就是这样。 – glibdud

+1

您是否真的想在迭代时使用'del data [key]'(这是不好的做法),或者您只是这么做以确保已知密钥不会迭代两次? – smci

+0

也不需要有'dict(input_data)',除非有机会输入不是字典(在你的例子中没有表示)。 – skrrgwasme

回答

2

我建议你只需运行一个对列表内涵:其一为所需的密钥,以及一个用于休息。按照所需的顺序将它们连接起来,而不是一次一个。这将关键步骤减少到构建输出的单个命令。

第一理解查找在字典所需按键;第二个查找“期望”列表中的任何字典键而不是

def format_data(input_data): 
    data = dict(input_data) 
    key_list = ["title", "slug", "date", "modified", "category", "tags"] 
    output = ["{}: {}".format(key.title(), data[key]) for key in key_list if key in data] + \ 
      ["{}: {}".format(key.title(), data[key]) for key in data if key not in key_list] 
    return "\n".join(output) 
0

要彻底修改,下面将采取主键的列表(你可以通过它们,如果你想或将其设置在一个配置文件),然后将这些设置在你的字典的开始。

我想我明白你的意思:

试试这个:

from collections import OrderedDict 
data = {'aaa': 'bbbb', 
'custom': 'data', 
'date': '2017-02-01', 
'foo': 'bar', 
'format': 'book', 
'slug': 'another-post-title', 
'title': 'Another Post Title'} 

def format_data(input_data): 
    primary_keys = ["title", "slug", "date", "modified", "category", "tags"] 
    data = OrderedDict((k, input_data.get(k)) for k in primary_keys + input_data.keys()) 
    output = [] 
    for key, value in data.items(): 
     if value: 
      output.append("{}: {}".format(key.title(), value)) 
    return "\n".join(output) 

print(format_data(data)) 

Title: Another Post Title 
Slug: another-post-title 
Date: 2017-02-01 
Aaa: bbbb 
Format: book 
Custom: data 
Foo: bar 
+0

我喜欢'OrderedDict'的想法,但是在迭代它们时不应该从集合中删除东西。先建立一个键列表,然后你可以在迭代列表时自由修改字典。实际上,smci对这个问题的评论正处于一个很好的位置 - 删除可能只是为了防止重复两遍。对于有序的字典,可能不再需要。 – skrrgwasme

+0

的确,我有一个替代方案的更新。 – Kelvin

+0

感谢您的回答。然而,我不能对关键字添加到输入字典的顺序做出假设(我逐行读取源文件并且源文件中的顺序是随机的)。我想我可以创建模板OrderedDict将所有已知键添加到预期的顺序,但是再次 - 源文件可能会丢失一些已知的键。我已经将这些要求添加到了我的问题中 - 您是否可以尝试更新您的答案以解决这些问题? –

0

我建议列表理解和pop()

def format_data(input_data): 
    data = dict(input_data) 

    keys = ["title", "slug", "date", "modified", "category", "tags"] 
    output = ['{}: {}'.format(key.title(), data.pop(key)) for key in keys if key in data] 

    output.extend(['{}: {}'.format(key.title(), val) for key, val in data.items()]) 

    return "\n".join(output) 

要对迭代过程中删除的关注 - 注意,迭代结束键列表,而不是字典进行评价,所以我不会认为这是一面红旗。

0

找到已知密钥和在输入字典中的项之间的差;使用itertools.chain遍历键的两个集合;捕获丢失键的KeyErrors并通过。无需复制输入并且不需要重复。

import itertools 
def format_data(input_data): 
    known_keys = ["title", "slug", "date", "modified", "category", "tags"] 
    xtra_keys = set(input_data.keys()).difference(known_keys) 
    output = [] 
    for key in itertools.chain(known_keys, xtra_keys): 
     try: 
      output.append("{}: {}".format(key.title(), data[key])) 
     except KeyError as e: 
      pass 
    return '\n'.join(output) 

data = {"tags": "one, two", 
     "slug": "post-title", 
     "date": "2017-02-01", 
     "title": "Post Title", 
     "foo": "bar"} 

>>> print format_data(data) 
Title: Post Title 
Slug: post-title 
Date: 2017-02-01 
Tags: one, two 
Foo: bar 
>>>