鉴于此数据:
foo kk type1 1 2 3
bar kk type2 3 5 1
我想创建一个列表字典的字典。
在Perl中,它被称为数组哈希的哈希。 它可以通过以下行实现(在此处可执行https://eval.in/118535)
push @{$hohoa{$name}{$type}},($v1,$v2,$v3);
Perl中$ hohoa的输出:
$VAR1 = {
'bar' => {
'type2' => [
'3',
'5',
'1'
]
},
'foo' => {
'type1' => [
'1',
'2',
'3'
]
}
};
在Python中使用它的方法是什么?
更新:为什么以下for loop
变体并未存储所有值?
#!/usr/bin/env python
import sys
import pprint
from collections import defaultdict
outerdict = defaultdict(dict)
with open('data.txt') as infh:
for line in infh:
name, _, type_, values = line.split(None, 3)
valist = values.split();
for i in range(len(valist)):
thval = valist[i];
outerdict[name][type] = thval
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(outerdict)
打印出来:
defaultdict(<type 'dict'>, {'foo': {<type 'type'>: '3'}, 'bar': {<type 'type'>: '1'}})
更新2:输出似乎有问题 当数据看起来像这样:
foo kk type1 1.2 2.10 3.3
bar kk type2 3.2 5.2 1.0
答案 0 :(得分:6)
这取决于你想要达到的目标;应该在内部字典中添加多少个键?
最简单的方法是为内部字典创建新的字典文字:
outerdict = {}
outerdict[name] = {type_: [v1, v2, v3]}
或者您可以根据需要使用dict.setdefault()
来实现内部字典:
outerdict.setdefault(name, {})[type_] = [v1, v2, v3]
或者您可以使用collections.defaultdict()
让它为您处理新值:
from collections import defaultdict
outerdict = defaultdict(dict)
outerdict[name][type_] = [v1, v2, v3]
逐行解析文件时,我会使用后者,尽管有点简化:
from collections import defaultdict
outerdict = defaultdict(dict)
with open(filename) as infh:
for line in infh:
name, _, type_, *values = line.split()
outerdict[name][type_] = [int(i) for i in values]
这使用Python 3语法将前3行的剩余空格分隔值捕获到values
。
Python 2版本将是:
with open(filename) as infh:
for line in infh:
name, _, type_, values = line.split(None, 3)
outerdict[name][type_] = map(int, values.split())
我将空格分割限制为仅3个分割(给出4个值),然后分别分割values
字符串。
要让最里面的列表为重复的(name, type_)
组合键累积所有值,您需要使用稍微复杂的defaultdict
设置;一个产生内部 defaultdict()
设置以产生list
值的产品:
outerdict = defaultdict(lambda: defaultdict(list))
with open(filename) as infh:
for line in infh:
name, _, type_, values = line.split(None, 3)
outerdict[name][type_].extend(map(int, values.split()))
对于您实际发布的文件,我完全使用不同的方法:
import csv
from itertools import islice
outerdict = defaultdict(lambda: defaultdict(list))
with open('ImmgenCons_all_celltypes_MicroarrayExp.csv', 'rb') as infh:
reader = csv.reader(infh, skipinitialspace=True)
# first row contains metadata we need
celltypes = next(reader, [])[3:]
# next two rows can be skipped
next(islice(infh, 2, 2), None)
for row in reader:
name = row[1]
for celltype, value in zip(celltypes, row[3:]):
outerdict[name][celltype].append(float(value))
答案 1 :(得分:1)
def make_strukture(lst_of_str):
result = {}
for i in my_strs:
data = i.split()
if data[0] in result.keys(): continue #Only one first key for foo, bar
result[data[0]] = {} #Create first key foo, bar-level
result[data[0]][data[2]] = list(data[3:]) #Skip kk and create second key with list
return result
#Below more comples data structure:
my_strs = ["foo kk type1 1 2 3", "foo kk type2 1 2 3", "bar kk type2 3 5 1"]
print make_strukture(my_strs)
打印结果:
{'foo':
{'type1': ['1', '2', '3']},
'bar':
{'type2': ['3', '5', '1']}
}
答案 2 :(得分:1)
另一个很好的方法是执行以下操作:
from collections import defaultdict
d = defaultdict(lambda: defaultdict(list))
# eg.
d["x"]["y"].append(100)
通过这种方式,您将创建一个默认值为list的许多字典的字典。
答案 3 :(得分:0)
您可以使用defaultdict
dict
和reduce
来使用普通dict.setdefault
,而不是使用text_data = """foo kk type1 1 2 3
bar kk type2 3 5 1"""
data = [line.split() for line in text_data.splitlines()]
# [['foo', 'kk', 'type1', '1', '2', '3'], ['bar', 'kk', 'type2', '3', '5', '1']]
var1 = {}
for row in data:
# row[:2] everything before leaf, [2] is the leaf, row[3:] remainder of 'values'
reduce(lambda a,b: a.setdefault(b, {}), row[:2], var1)[2] = row[3:]
# {'foo': {'kk': {2: ['1', '2', '3']}}, 'bar': {'kk': {2: ['3', '5', '1']}}}
。这是一个可以包含在函数中的示例:
def nested_dict(sequences, n, converter=lambda L: L):
ret = {}
for seq in sequences:
reduce(lambda a,b: a.setdefault(b, {}), seq[:n-1], ret)[n] = map(converter, seq[n:])
return ret
nested_dict(data, 2)
#{'foo': {2: ['type1', '1', '2', '3']}, 'bar': {2: ['type2', '3', '5', '1']}}
nested_dict(data, 3)
# {'foo': {'kk': {3: ['1', '2', '3']}}, 'bar': {'kk': {3: ['3', '5', '1']}}}
nested_dict(data, 3, int)
# {'foo': {'kk': {3: [1, 2, 3]}}, 'bar': {'kk': {3: [3, 5, 1]}}}
# ...
然后,将其包装到具有值的可选转换器的函数中,例如:
{{1}}