javascript - 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}}
我想编写一个代码,可以从输入对象展开所有案例,这个字典对象inputs
在cases
里面并且cases
已经嵌套inputs
了 this inputs
can 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
这些输入集进一步可以有“案例”(嵌套案例和输入)
我输入的所有个别案例。
请帮忙
解决方案
你有两个问题:
首先你的代码,你不检查变量是否定义
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 False和true not True,JavaScript 只知道 false 和 true 不知道任何其他形式。
如果你有值 none,你必须把它放在 '' like {'display':'none'}
在您的输入中,您必须将所有 False 替换为 false,
在您的输出中,您必须将所有 False 替换为 false,将 True 替换为 true,将 none 替换为“none”
祝你好运☺</p>
推荐阅读
- css - Bootstrap 4 导航链接悬停效果
- javascript - ReactJS - 什么而不是 JWT 来保持会话
- java - 尽管有互联网连接,该应用程序始终显示没有互联网连接
- java - 为什么有些 Java EE API 是在 Java SE 中实现的?
- javascript - Vue,获取选择选项的值和名称
- java - 如何为不需要打开应用程序的android应用程序创建离线通知
- excel - 使用用户表单进行数据库查找
- c# - 使用 xmlreader 阅读时如何跳过无效的 xml 节点?
- c# - C# 将泛型列表传递给 WinForm 构造函数
- google-apps-script - 如何使用脚本将条件格式规则从一张纸复制到另一张纸?