首页 > 解决方案 > Javascript:如何在 javascript 中编写递归函数来展开字典对象?

问题描述

我有一个字典对象:

const inputs = {'model_class': 'Conditional', 'name': 'SelPlotting', 'type': 'conditional', 'cases': [{'model_class': 'ConditionalWhen', 'value': 'HeatMap', 'inputs': [{'model_class': 'DataToolParameter', 'name': 'InFile', 'argument': '--InFile', 'type': 'data', 'label': 'Input file', 'help': 'Tabular data file', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'none', 'extensions': ['tabular'], 'edam': {'edam_formats': ['format_3475'], 'edam_data': ['data_0006']}, 'multiple': false, 'options': {'hda': [], 'hdca': []}}, {'model_class': 'TextToolParameter', 'name': 'IndexColumn', 'argument': '--IndexColumn', 'type': 'text', 'label': 'Index Column', 'help': 'Column name that contains index as row/sample names ', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'Index', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'x_label', 'argument': '--x_label', 'type': 'text', 'label': 'Label for x-axis', 'help': 'A label that describes x axis', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'x-axis', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'y_label', 'argument': '--y_label', 'type': 'text', 'label': 'Label for y-axis', 'help': 'A label that describes y axis', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'y-axis', 'area': false, 'datalist': []}]}, {'model_class': 'ConditionalWhen', 'value': 'BoxPlot', 'inputs': [{'model_class': 'DataToolParameter', 'name': 'InFile', 'argument': '--InFile', 'type': 'data', 'label': 'Input file', 'help': 'Tabular data file', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'none', 'extensions': ['tabular'], 'edam': {'edam_formats': ['format_3475'], 'edam_data': ['data_0006']}, 'multiple': false, 'options': {'hda': [], 'hdca': []}}, {'model_class': 'TextToolParameter', 'name': 'Feature', 'argument': '--Features', 'type': 'text', 'label': 'Feature name', 'help': 'Name of the feature (column name)', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'Feature', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'Label', 'argument': '--Label', 'type': 'text', 'label': 'Class label column', 'help': 'Name of the column that contains class label', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'class label', 'area': false, 'datalist': []}]}, {'model_class': 'ConditionalWhen', 'value': 'ScatterPlot', 'inputs': [{'model_class': 'DataToolParameter', 'name': 'InFile', 'argument': '--InFile', 'type': 'data', 'label': 'Input file', 'help': 'Tabular data file', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'none', 'extensions': ['tabular'], 'edam': {'edam_formats': ['format_3475'], 'edam_data': ['data_0006']}, 'multiple': false, 'options': {'hda': [], 'hdca': []}}, {'model_class': 'Conditional', 'name': 'PlotType', 'type': 'conditional', 'cases': [{'model_class': 'ConditionalWhen', 'value': '2D', 'inputs': [{'model_class': 'TextToolParameter', 'name': 'Features1', 'argument': '--RotationX', 'type': 'text', 'label': 'First feature', 'help': 'Feature column name', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'feature1', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'Features2', 'argument': '--RotationY', 'type': 'text', 'label': 'Second feature', 'help': 'Feature column name', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'feature2', 'area': false, 'datalist': []}]}, {'model_class': 'ConditionalWhen', 'value': '3D', 'inputs': [{'model_class': 'TextToolParameter', 'name': 'Features1', 'argument': '--RotationX', 'type': 'text', 'label': 'First feature', 'help': 'Feature column name', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'feature1', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'Features2', 'argument': '--RotationY', 'type': 'text', 'label': 'Second feature', 'help': 'Feature column name', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'feature2', 'area': false, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'Features3', 'argument': '--FigHight', 'type': 'text', 'label': 'Third feature', 'help': 'Feature column name', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'feature3', 'area': false, 'datalist': []}]}], 'test_param': {'model_class': 'SelectToolParameter', 'name': 'SelectPlot', 'argument': '', 'type': 'select', 'label': 'Scatter Plot type', 'help': 'Scatter Plot type 2D or 3D.', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': '2D', 'options': [['2D', '2D', false], ['3D', '3D', False]], 'display': 'none', 'multiple': false, 'textable': False}}, {'model_class': 'TextToolParameter', 'name': 'Label', 'argument': '--Label', 'type': 'text', 'label': 'Class label column', 'help': 'Name of the column that contains class label', 'refresh_on_change': false, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'class label', 'area': false, 'datalist': []}]}, {'model_class': 'ConditionalWhen', 'value': 'WordCloud', 'inputs': [{'model_class': 'DataToolParameter', 'name': 'InFile', 'argument': '--InFile', 'type': 'data', 'label': 'Input file', 'help': 'Fasta file with peptides', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'none', 'extensions': ['fasta'], 'edam': {'edam_formats': ['format_1929'], 'edam_data': ['data_2044']}, 'multiple': false, 'options': {'hda': [], 'hdca': []}}, {'model_class': 'IntegerToolParameter', 'name': 'd', 'argument': '--FragSize', 'type': 'integer', 'label': 'Size of ngrams', 'help': 'Size of ngrams', 'refresh_on_change': false, 'min': 'none', 'max': 'none', 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': '4', 'area': false, 'datalist': []}]}], 'test_param': {'model_class': 'SelectToolParameter', 'name': 'Plot', 'argument': '', 'type': 'select', 'label': 'Data plotting method', 'help': 'Data plotting method', 'refresh_on_change': true, 'optional': false, 'hidden': false, 'is_dynamic': false, 'value': 'HeatMap', 'options': [['Heat Map', 'HeatMap', false], ['Box Plot', 'BoxPlot', false], ['Scatter Plot', 'ScatterPlot', false], ['Word Cloud', 'WordCloud', False]], 'display': 'none', 'multiple': false, 'textable': false}}

为了清楚起见,一个较小的对象:

const example2 = {'model_class': 'Conditional',
 'name': 'selmethod',
 'type': 'conditional',
 'cases': [{'model_class': 'ConditionalWhen',
   'value': 'advance',
   'inputs': [{'model_class': 'TextToolParameter',
     'name': 'classlabel',
     'argument': '--SlcClassLabel',
     'type': 'text',
     'label': 'Name the column for class label',
     'help': 'Select Class Label',
     'refresh_on_change': False,
     'optional': False,
     'hidden': False,
     'is_dynamic': False,
     'value': '',
     'area': False,
     'datalist': []}]},
  {'model_class': 'ConditionalWhen', 'value': 'default', 'inputs': []}],
 'test_param': {'model_class': 'SelectToolParameter',
  'name': 'method',
  'argument': '--Method',
  'type': 'select',
  'label': 'Option to merg data',
  'help': 'Split file if class labels are present',
  'refresh_on_change': True,
  'optional': False,
  'hidden': False,
  'is_dynamic': False,
  'value': 'default',
  'options': [[' Merge data and add class labels', 'advance', False],
   [' Merge data without adding class labels', 'default', True]],
  'display': None,
  'multiple': False,
  'textable': False}} 

我想编写一个代码,可以从输入对象展开所有案例,这个字典对象inputscases里面并且cases已经嵌套inputs了 this inputscan have cases

function UnwrapInputs ( cases ) {
    for (var i = 0; i < cases.length; i++) {
        console.log(cases[i])
        for (var j =0; j < cases[i].inputs.length; j++) {
            if (Object.keys(cases[i].inputs[j])) {
                UnwrapInputs(cases[i].inputs[j].cases)
            }

           console.log(cases[i].inputs[j].cases)

        }
    }   

我尝试了类似上述功能的方法,但它确实有效:

我想打开所有案例,我想输出如下所示的内容

{'model_class': 'ConditionalWhen', 'value': 'HeatMap', 'inputs': [{'model_class': 'DataToolParameter', 'name': 'InFile', 'argument': '--InFile', 'type': 'data', 'label': 'Input file', 'help': 'Tabular data file', 'refresh_on_change': True, 'optional': False, 'hidden': False, 'is_dynamic': False, 'value': None, 'extensions': ['tabular'], 'edam': {'edam_formats': ['format_3475'], 'edam_data': ['data_0006']}, 'multiple': False, 'options': {'hda': [], 'hdca': []}}, {'model_class': 'TextToolParameter', 'name': 'IndexColumn', 'argument': '--IndexColumn', 'type': 'text', 'label': 'Index Column', 'help': 'Column name that contains index as row/sample names ', 'refresh_on_change': False, 'optional': False, 'hidden': False, 'is_dynamic': False, 'value': 'Index', 'area': False, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'x_label', 'argument': '--x_label', 'type': 'text', 'label': 'Label for x-axis', 'help': 'A label that describes x axis', 'refresh_on_change': False, 'optional': False, 'hidden': False, 'is_dynamic': False, 'value': 'x-axis', 'area': False, 'datalist': []}, {'model_class': 'TextToolParameter', 'name': 'y_label', 'argument': '--y_label', 'type': 'text', 'label': 'Label for y-axis', 'help': 'A label that describes y axis', 'refresh_on_change': False, 'optional': False, 'hidden': False, 'is_dynamic': False, 'value': 'y-axis', 'area': False, 'datalist': []}]}

简而言之,这里的输入有几个cases,每个案例都有自己的inputs这些输入集进一步可以有“案例”(嵌套案例和输入)

我输入的所有个别案例。

请帮忙

标签: javascriptrecursion

解决方案


你有两个问题:

首先你的代码,你不检查变量是否定义

function UnwrapInputs (cases) {
    for (var i = 0; i < cases.length; i++) {
        console.log(cases[i])
        if (typeof(cases[i].inputs) !== 'undefined') {
            for (var j =0; j < cases[i].inputs.length; j++) {
                if (typeof(cases[i].inputs[j].cases) !== 'undefined') {
                    UnwrapInputs(cases[i].inputs[j].cases)
                }
            }
        }
    }   
}  
UnwrapInputs(inputs.cases);

第二个也是重要的问题是你的投入

您必须将每个键和值放在 '' 之间,例如 {'key' : 'value'}

你只能省略 '' 代表数字,真或假。

false not Falsetrue not True,JavaScript 只知道 false 和 true 不知道任何其他形式。

如果你有值 none,你必须把它放在 '' like {'display':'none'}

在您的输入中,您必须将所有 False 替换为 false,

在您的输出中,您必须将所有 False 替换为 false,将 True 替换为 true,将 none 替换为“none”

祝你好运☺</p>


推荐阅读