如何根据文件名从列表创建嵌套字典?

问题描述 投票:0回答:1

我有一个装满文件的文件夹。我需要加载这些文件并重建嵌套字典。文件名包括字典的结构。例如,一个文件名为“vz_ERA_Neural_Water_Forecast.npy”。 “vz”是原始字典名称,“ERA”是第一个键,“Neural”是第二个键,依此类推。有些文件仅嵌套 3 层,有些则嵌套 5 层。

这是我尝试过的代码:

# Get list of all the files to load
files = os.listdir(Path(fc.selected,'vz_save'))
# remove from list name of file that contains files we care about and hidden files
files.remove('fileNamesAndTypes.txt')
for file in files:
    if file.startswith('.'):
        files.remove(file)


# creat an empty dictionary in which to eventually allocate the loaded files
vz_check = {}

for file in files: 
    #print(file)
    ext = Path(file).suffix
    fileNoExt = Path(file).stem # remove the file extension (file type)
    keys = fileNoExt.split('_')
    keys.remove('vz')
        
    # find matching fileNoExt to value in fileNamesAndTypes[key]
    reloadedType = fileNamesAndTypes_check[fileNoExt]
        
        
    # load the file?
    if reloadedType == str:
        #print(f"type=str; reloadedType={reloadedType}")
        reload = open(Path(fc.selected,'vz_save',file),'rb')
        contents = reload.read()
        print(contents)
        for key in reversed(keys):
            vz_check = {key: vz_check}
    elif reloadedType == xr.core.dataset.Dataset:
        #print(f"type=xr.core.dataset.Dataset; reloadedType={reloadedType}")
    elif reloadedType == xr.core.dataarray.DataArray:
        #print(f"type=xr.core.dataarray.DataArray; reloadedType={reloadedType}")
    elif reloadedType == int:
        #print(f"type=int; reloadedType={reloadedType}")
    elif reloadedType == list:
        #print(f"type=list; reloadedType={reloadedType}")
    elif reloadedType == np.ndarray:
        #print(f"type=np.ndarray; reloadedType={reloadedType}")

我最终得到的是一个非常丑陋的超级嵌套,每个级别只有一行越来越深的单一键,而不是每个级别都有多个键。 vz_check result screencap

最终结果应该是这样的: vz original screencap

如何让它自动加载所有嵌套零件并将其缝合在一起。有没有更好的方法来解决这个问题?

编辑:

在等待帮助的过程中,我想出了这个解决方案,我觉得它非常丑陋,但会完成工作。必须有更好的方法来做到这一点。

def buildDict(keyss,contentss,theDict):
    if len(keyss) == 1:
        theDict = {keyss: contentss}
    elif len(keyss) == 2:
        theDict = {keyss[0] : { keyss[1] : contentss } }
    elif len(keyss) == 3: 
        theDict = {keyss[0] : {keyss[1] : {keyss[2] : contentss } } }
    elif len(keyss) == 4: 
        theDict = {keyss[0] : {keyss[1] : {keyss[2] : {keyss[3] : contentss } } } }
    elif len(keyss) == 5: 
        theDict = {keyss[0] : {keyss[1] : {keyss[2] : {keyss[3] : {keyss[4] : contentss } } } } }
python-3.x dictionary nested
1个回答
0
投票

这是解决方案。

因为我知道字典 vz 应该是什么样子,所以我只是将其预设为结构并使用下面的代码来填充空白。目前它仅适用于“reloadedType == str”,但其余的应该相对容易理解。我确信有更好的方法,但这行得通。

# load the individual files and reconstruct the dictionary
vz_reloaded = {
key1: {
    key2: {
        sub_key: [] for sub_key in [
            'Reof', 'Training_Data', 'Filetype', 'Polarization',
            'Coeffs', 'Modes', 'Models', 'Score', 'RMSE', 'Reof_forecast', 'Input_Images',
            'Reof_hindcast', 'Hindcast', 'Forecast', 'Best_Index', 'Difference',
            'Water_Hindcast', 'Water_Forecast'
        ]
    }
    for key2 in ['Polynomial', 'Neural']
}
for key1 in ['Q', 'ERA']
}

# Get list of all the files to load
files = os.listdir(Path(fc.selected,'vz_save'))
# remove from list name of file that contains files we care about and hidden files
files.remove('fileNamesAndTypes.txt')
for file in files:
    if file.startswith('.'):
        files.remove(file)

# creat an empty dictionary in which to eventually allocate the loaded files
vz_reloaded = {}

for file in files: 
    #print(file)
    ext = Path(file).suffix
    fileNoExt = Path(file).stem # remove the file extension (file type)
    keys = fileNoExt.split('_')
    keys.remove('vz')
        
    # find matching fileNoExt to value in fileNamesAndTypes[key]
    reloadedType = fileNamesAndTypes_check[fileNoExt]
        
        
    # load the file?
    if reloadedType == str:
        #print(f"type=str; reloadedType={reloadedType}")
        reload = open(Path(fc.selected,'vz_save',file),'rb')
        contents = reload.read()
    elif reloadedType == xr.core.dataset.Dataset:
        #print(f"type=xr.core.dataset.Dataset; reloadedType={reloadedType}")
        pass
    elif reloadedType == xr.core.dataarray.DataArray:
        #print(f"type=xr.core.dataarray.DataArray; reloadedType={reloadedType}")
        pass
    elif reloadedType == int:
        #print(f"type=int; reloadedType={reloadedType}")
        pass
    elif reloadedType == list:
        #print(f"type=list; reloadedType={reloadedType}")
        pass
    elif reloadedType == np.ndarray:
        #print(f"type=np.ndarray; reloadedType={reloadedType}")
        pass
    
    # Here's the part that puts the pieces of the dictionary back in. 
    try:
        if len(keys)==3:
            vz_reloaded[keys[0]][keys[1]][keys[2]] = contents
        elif len(keys)==4: 
            vz_reloaded[keys[0]][keys[1]][keys[2]][keys[3]] = contents
        elif len(keys)==5: 
            vz_reloaded[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]] = contents
    except:
        print(f"This key set is a problem: {keys}")
        print(f"Type: {reloadedType}")
© www.soinside.com 2019 - 2024. All rights reserved.