以任意顺序处理字典键

时间:2017-02-01 18:45:47

标签: python dictionary iteration

我想将字典转换为字符串。什么是初级水平的问题很复杂,我必须遵守的规则很少:

  • 有一个已知密钥的列表,特别是任意顺序
  • 每个已知密钥都是可选的,即它可能不存在于字典
  • 保证字典中至少有一个已知密钥
  • 字典可能包含其他键;他们必须来自已知的钥匙,他们的顺序并不重要
  • 我不能假设关键字将被添加到词典

在其他词典键之前处理某些字典键的pythonic方法是什么?

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

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()行并复制输入数据结构以允许其修改而没有副作用。

总结一下,如何在特定顺序和其他键之前处理某些键?

4 个答案:

答案 0 :(得分:2)

我建议您只运行一对列表推导:一个用于所需的键,另一个用于其余键。按批量顺序连接它们,而不是一次连接一个。这减少了构建输出的单个命令的关键步骤。

第一个理解在dict中查找所需的键;第二个在“所需”列表中查找任何字典键

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)

答案 1 :(得分: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

答案 2 :(得分: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)

关于在迭代期间删除的问题 - 注意迭代是在键列表上,而不是被评估的字典,所以我不会认为是红旗。

答案 3 :(得分:0)

找出输入字典中已知键和键之间的区别;使用itertools.chain迭代两个 sets 键;捕获缺少键的KeyErrors并传递。无需复制输入,也无需复制。

public String[] splitIntoLine(String input, int maxCharInLine){

StringTokenizer tok = new StringTokenizer(input, " ");
StringBuilder output = new StringBuilder(input.length());
int lineLen = 0;
while (tok.hasMoreTokens()) {
    String word = tok.nextToken();

    while(word.length() > maxCharInLine){
        output.append(word.substring(0, maxCharInLine-lineLen) + "\n");
        word = word.substring(maxCharInLine-lineLen);
        lineLen = 0;
    }

    if (lineLen + word.length() > maxCharInLine) {
        output.append("\n");
        lineLen = 0;
    }
    output.append(word).append(" ");

    lineLen += word.length() + 1;
}
// output.split();
// return output.toString();
return output.toString().split("\n"); 
}