嵌套字典 - 迭代关闭

时间:2018-01-11 14:10:23

标签: python dictionary

我正在尝试将一些数据转换为嵌套字典,其中有一个通用的State键,然后是与数字匹配的特定Area键(如下所示)。

为了使数据更好地形成,我有一个痛苦的三重循环,如下所示。但是,它无法正常工作,因为它只保存每个州/地区的最后一个号码。我试图调整此代码,但没有看到在哪里修复我的迭代,使其正确循环遍历每个迭代器并相应地放置增长数字。我想要获得的输出与实际输出相比低于 - 虽然没有错误消息,但输出不是我的目标。

感谢您对此提供的帮助,并且好奇如果在字典中有字典时这是一种非常低效(或没有问题)的迭代方式。

state=['NJ', 'NY', 'TX', 'CA', 'OH']
area=['North','South']
growth = [['State', 'North', 'South'],
    ['NJ', '5.09', '3'],
    ['NY', '0', '1',],
    ['TX', '8','5.54'],
    ['CA', '6', '1'],
    ['OH', '7.77', '5']]

nested_dict={}
for i in range(1,len(growth)):
    nested_dict[growth[i][0]]=dict()

for i in range(0,len(state)):
    for j in range(0,len(area)):
        for k in range(1,len(growth[0])):
            nested_dict[state[i]][area[j]]=float(growth[i+1][k])

预期产出:

{'CA': {'North': 6.0, 'South': 1.0},
 'NJ': {'North': 5.09, 'South': 3.0},
 'NY': {'North': 0.0, 'South': 1.0},
 'OH': {'North': 7.77, 'South': 5.0},
 'TX': {'North': 8.0, 'South': 5.54}}

输出错误:

{'CA': {'North': 1.0, 'South': 1.0},
 'NJ': {'North': 3.0, 'South': 3.0},
 'NY': {'North': 1.0, 'South': 1.0},
 'OH': {'North': 5.0, 'South': 5.0},
 'TX': {'North': 5.54, 'South': 5.54}}

编辑上述内容以反映评论

2 个答案:

答案 0 :(得分:1)

您要将growth行中的第2和第3个值分配给所有statearea配对,并使用最里面的循环:

for k in range(1,len(growth[0])):

所以你最终分配了两次:

# first iteration
i = 0   # state: NJ
j = 0   # area: North
k = 1   # second column in growth
nested_dict[state[0]][area[0]] = float(growth[0+1][1])
# nested_dict['NJ']['North'] = float(['NJ', '5.09', '3'][1] == '5.09')

# second iteration
i = 0   # state: NJ
j = 0   # area: North
k = 2   # third column in growth
nested_dict[state[0]][area[0]] = float(growth[0+1][2])
# nested_dict['NJ']['North'] = float(['NJ', '5.09', '3'][2] == '3')

请注意ij未改变的方式!

你根本不需要第三个循环,你已经选择了你的州和地区;只需从表中选择正确的值,使用area索引加1来映射到右列:

for i in range(len(state)):
    for j in range(len(area)):
        nested_dict[state[i]][area[j]] = float(growth[i + 1][j + 1])
        #                                       instead of k ^^^^^

现在,使用索引单字母索引会使您难以遵循代码。你应该真正了解这里的enumerate() function,以生成索引:

for row, state_name in enumerate(state, 1):   # starting at row 1
    for col, area_name in enumerate(area, 1): # starting at column 1
        nested_dict[state_name][area_name] = float(growth[row][col])

通过state直接循环,并使用enumerate()添加从1开始的索引,您将获得州名('NJ'指向growth1)的正确索引。 area列表也是如此('North'1,或'South'2)。

但是,您已经在growth矩阵中拥有了所有行名和列名,因此您可以直接使用它生成所有词典:

area_names = growth[0][1:]
nested_dict = {
    state: {area: float(value) for area, value in zip(area_names, row)}
    for state, *row in growth[1:]
}

zip() function将区域名称(位于growth的第一行)与每列的值(存储在row中)放在一起,第一个值转移到{ {1}})。

注意state循环; Python将每个列表从for state, *row in ..解压缩为两个变量;第一个值存储在growth中,由于staterow为前缀,所有剩余值都存储在*中:

row

这真的是你所需要的:

>>> state, *row = ['NJ', '5.09', '3']
>>> state
'NJ'
>>> row
['5.09', '3']

最后但并非最不重要的是,如果所有这些数据来自CSV文件,您可能应该使用csv module代替:

>>> area_names = growth[0][1:]
>>> nested_dict = {
...     state: {area: float(value) for area, value in zip(area_names, row)}
...     for state, *row in growth[1:]
... }
{'NJ': {'North': 5.09, 'South': 3.0}, 'NY': {'North': 0.0, 'South': 1.0}, 'TX': {'North': 8.0, 'South': 5.54}, 'CA': {'North': 6.0, 'South': 1.0}, 'OH': {'North': 7.77, 'South': 5.0}}
>>> from pprint import pprint
>>> pprint(_)
{'CA': {'North': 6.0, 'South': 1.0},
 'NJ': {'North': 5.09, 'South': 3.0},
 'NY': {'North': 0.0, 'South': 1.0},
 'OH': {'North': 7.77, 'South': 5.0},
 'TX': {'North': 8.0, 'South': 5.54}}

import csv nested_dict = {} with open(somefile, 'r', newline='') as f: reader = csv.DictReader(f) for row in reader: state = row.pop('State') nested_dict[state] = {k: float(v) for k, v in row.items()} 对象将CSV文件的第一行作为列名,并为每行生成一个字典。如果您的州列使用名称旁边的引号,您甚至可以使用DictReader()让模块自动将未引用的任何内容转换为quoting=csv.QUOTE_NONNUMERIC值。

答案 1 :(得分:1)

除非我遗漏了一些重要内容,否则你不需要任何嵌套循环,也不需要其他两个列表。单个(嵌套)字典理解就足够了。

@Override
public void onBackPressed() {
    if (isViewD_Visible) {
        // show View-C
        isViewD_Visible = false;
    }else {
        // ...
    }
}

(假设result = {st: {"North": float(n), "South": float(s)} for (st, n, s) in growth[1:]} print(result) # {'OH': {'North': 7.77, 'South': 5.0}, 'TX': {'North': 8.0, 'South': 5.54}, # 'NJ': {'North': 5.09, 'South': 3.0}, 'NY': {'North': 0.0, 'South': 1.0}, # 'CA': {'North': 6.0, 'South': 1.0}} 列表包含的每个州不超过一次,并且第一,第二和第三项始终是州,北和南值,按此顺序。)