Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在嵌套字典的锯齿状列表中使用_Python_Dictionary_Jagged Arrays_Awkward Array - Fatal编程技术网

Python 在嵌套字典的锯齿状列表中使用

Python 在嵌套字典的锯齿状列表中使用,python,dictionary,jagged-arrays,awkward-array,Python,Dictionary,Jagged Arrays,Awkward Array,我有一个很大的嵌套字典,其中有锯齿状列表“c”: x = {'first_block': {'unit1': {'a': (3,5,4), 'b': 23, 'c': [10]}, 'unit2': {'a': (5,8,7), 'b': 15, 'c': [20,10]}, 'unit10k': {'a': (2,4,9), 'b': 10, 'c': [6,10,20,5]}}, 'second_block':

我有一个很大的嵌套字典,其中有锯齿状列表“c”:

x = {'first_block': 
     {'unit1': {'a': (3,5,4), 'b': 23, 'c': [10]}, 
      'unit2': {'a': (5,8,7), 'b': 15, 'c': [20,10]}, 
      'unit10k': {'a': (2,4,9), 'b': 10, 'c': [6,10,20,5]}},
     
      'second_block': 
       {'unit1' : {'a': (8,20,14), 'b': 10, 'c': [17,12,9]}, 
        'unit2' : {'a': (9,25,50), 'b': 15, 'c': [17,15,9,4,12]}, 
        'unit12k': {'a': (12,24,9), 'b': 23, 'c': [12,22,15,4]}},
     
      'millionth_block': 
      {'unit1': {'a': (35,64,85), 'b': 64, 'c': [50]}, 
       'unit2': {'a': (56,23,34), 'b': 55, 'c': [89,59,77]},
       'unit5k': {'a': (90,28,12), 'b': 85, 'c': [48,90,27,59]}}}  
“c”的元素是点标签

对于“c”中的每个唯一点标签,我希望生成“b”中相应值的过滤列表

例如,“first_block”在“c”中有唯一的元素:5,6,10,20

我想获得/提取每个“块”的以下列表,以列出与“c”中特定值相关的“b”的每个值,例如

first_block:
5: [10]
6: [10]
10: [10,15,23]
20: [10,15]
second_block:
4: [15,23]
9: [10,15]
12: [10,15,23]
15: [15,23]
17: [10,15]
22: [23]
etc.
考虑到“c”是参差不齐的,你对如何创造这种结果有什么想法吗

我们一直试图通过转换为笨拙的数组来实现这一点,但目前文档很少,而且真的不知道如何在笨拙的数组中实现这一点


也可以接受不涉及尴尬的pythonic建议。试试这个,它可以完全复制您想要的内容(包括排序)

输出:

first_block
5 [10]
6 [10]
10 [23, 15, 10]
20 [15, 10]
second_block
4 [15, 23]
9 [10, 15]
12 [10, 15, 23]
15 [15, 23]
17 [10, 15]
22 [23]
millionth_block
27 [85]
48 [85]
50 [64]
59 [55, 85]
77 [55]
89 [55]
90 [85]

试试这个,它会完全复制您想要的内容(包括排序)

输出:

first_block
5 [10]
6 [10]
10 [23, 15, 10]
20 [15, 10]
second_block
4 [15, 23]
9 [10, 15]
12 [10, 15, 23]
15 [15, 23]
17 [10, 15]
22 [23]
millionth_block
27 [85]
48 [85]
50 [64]
59 [55, 85]
77 [55]
89 [55]
90 [85]

我将尝试给出一个笨拙的数组解决方案

首先,我们需要知道数据集中的哪些内容是真正的扩展。我知道您可能有数百万个块,但这意味着您不应该使用具有唯一字符串值键的dict来表示它们。创建字符串、比较字符串和按字符串查找内容的成本(尽管dict的哈希表对这一点有很大帮助)不是一种扩展的好方法,尤其是当这些字符串中的唯一信息是排序时

在我看来,单位的数量也是可变的(因为最后一个单位被命名为“unit10k”、“unit12k”和“unit5k”)

最后,我重新阅读了您的问题陈述,但似乎名为“a”的字段没有进入问题。我不理它

因此,我认为您的数据结构会更好:

as_python=[
#第一街区
[
#第一单元
{“b”:23,“c”:[10]},
#第二单元
{“b”:15,“c”:[20,10]},
# ...
#第10k单元
{“b”:10,“c”:[6,10,20,5]},
],
#第二街区
[
#第一单元
{“b”:10,“c”:[17,12,9]},
#第二单元
{“b”:15,“c”:[17,15,9,4,12]},
# ...
#第12k单元
{“b”:23,“c”:[12,22,15,4]},
],
# ...
#第百万块
[
#第一单元
{“b”:64,“c”:[50]},
#第二单元
{“b”:55,“c”:[89,59,77]},
# ...
#第15k单元
{“b”:85,“c”:[48,90,27,59]},
],
]
解决这个问题的一个办法是

results=[]
对于as_python中的块:
块_结果={}
对于块中的单元:
b=单位[“b”]#只查找b一次
对于单位[“c”]中的c:
如果c不在块_结果中:
块_结果[c]=[]
块结果[c]。追加(b)
results.append(block_result)
导致

[
{10: [23, 15, 10], 20: [15, 10], 6: [10], 5: [10]},
{17: [10, 15], 12: [10, 15, 23], 9: [10, 15], 15: [15, 23], 4: [15, 23], 22: [23]},
{50: [64], 89: [55], 59: [55, 85], 77: [55], 48: [85], 90: [85], 27: [85]},
]
这应该很快。(对于未编译、动态类型的虚拟机,仅使用内置Python类型的短循环速度惊人。根据我的经验,仅使用内置Python类型是关键。)

至于笨拙的数组,在调用Numba(JIT compiled
for
loops)之前,我只能使用向量化(即“NumPy-like”)操作完成一半,这表明库需要一个“groupby”函数

当然,您可以在Numba中完成全部工作,这通常是最快的解决方案,但这个问题主要取决于分组和唯一性,在Python中,分组和唯一性最自然地由dict或set完成,但是很难让Numba推断出除纯数字和数组之外的任何类型。(为了JIT编译代码并使之快速,Numba必须知道它们的类型,但是Python类型注释是最新的,它们仍然被合并到Numba中。)

因此,让我们先把上面的数据结构变成一个笨拙的数组。根据您的数据源,有不同的方法来实现这一点(已完成),但我将让
ak.Array
迭代上述Python数据结构

>>作为ak导入
>>>as_笨拙=ak.Array(as_python)
通常,如果我们有一个“X和Y的所有组合”问题,我们希望使用。我们不能马上使用它,因为“b”数据和“c”数据有不同的深度:

>>as_ouk=ak.Array(as_python)
>>>b.很尴尬
并记录在案。我们最终希望将这些b-c对按c分组,我们至少可以对它们进行排序:

排序=展平[ak.argsort(flatted.c,axis=-1)] >>>分类

所以在这一点上,我们切换到Numba。这个问题比原来的问题简单得多,因为要分组的数据已经被排序了:我们只需要查看值何时更改为插入边界。笨拙的数组可以作为参数传递给Numba,但它们是不可变的。要创建新阵列,请使用。注意:在开发这样的函数时,请分小步进行,并删除
@nb.njit
,以便在不进行JIT编译的情况下进行尝试(确保在尝试解决类型错误之前所做的操作是正确的)

将numba作为nb导入
@nb.njit
def分组依据(输入、输出):
对于输入中的块:
output.begin_list()
output.begin_list()
last=block[0]。c#注意:假设len(block)>=1
对于块中的单元:
如果单位为c!=最后:
output.end_list()
output.begin_list()
输出追加(单位)
最后=单位c
output.end_list()
output.end_list()
返回输出
input
是我们刚刚创建的数组(
sorted
),而
output
是一个数组生成器,它可以转换为int
x = {'first_block': 
 {'unit1': {'a': (3,5,4), 'b': 23, 'c': [10]}, 
  'unit2': {'a': (5,8,7), 'b': 15, 'c': [20,10]}, 
  'unit10k': {'a': (2,4,9), 'b': 10, 'c': [6,10,20,5]}},
 
  'second_block': 
   {'unit1' : {'a': (8,20,14), 'b': 10, 'c': [17,12,9]}, 
    'unit2' : {'a': (9,25,50), 'b': 15, 'c': [17,15,9,4,12]}, 
    'unit12k': {'a': (12,24,9), 'b': 23, 'c': [12,22,15,4]}},
 
  'millionth_block': 
  {'unit1': {'a': (35,64,85), 'b': 64, 'c': [50]}, 
   'unit2': {'a': (56,23,34), 'b': 55, 'c': [89,59,77]},
   'unit5k': {'a': (90,28,12), 'b': 85, 'c': [48,90,27,59]}}}  
   
result = {};
for blocks in x.keys():
    cs = {};
    for unit in x[blocks].keys():
       for c in x[blocks][unit]['c']:
            #retrieve array of b value for the c key or take [], then concat the b value, then apply set function to remove double, then convert to list
            cs[str(c)] = list(set(((cs.get(str(c)) or []) + [x[blocks][unit]['b']])))
    result[blocks] = cs;

print(result);