我们需要帮助来解决此问题,我们企业中没人能做到。
我们有一个像这样的字符串:
- name
- type
- string
- validation
- required
- minLength
- 4
- maxLength
- 20
- optionIn
- option1
- option2
- option3
- option4
- password
- type
- string
- validation
- required
- minLength
- 6
- maxLength
- 30
- date
- type
- date
我们需要生成一个像这样的对象:
{
name: {
type: 'string',
validation: {
required: true,
minLength: 4,
maxLength: 20,
optionIn: ['option1', 'option2', 'option3', 'option4']
}
},
password: {
type: 'string',
validation: {
required: true,
minLength: 6,
maxLength: 30
}
},
date: {
type: 'date'
}
}
一些使它真正成为一项复杂任务的事情:
如果最后一个嵌套项只是一个,则使他成为前一个键的值。如果最后一个嵌套项目不止一个,则它们将成为一个数组,并且该数组是前一个键的值。
编辑: 感谢@adiga的真知灼见,因为“队友”有一个嵌套项,所以对“必需”的示例成为具有true值的对象
这是一项艰巨而复杂的任务,可以根据需要使用库。
答案 0 :(得分:2)
我想出的解决方案是一个两步过程。
首先,我以最简单的方式将parse()
inputStr
转换成中间形式,最终看起来像这样:
{
"name": {
"type": {
"string": null
},
"validation": {
"required": null,
"minLength": {
"4": null
},
"maxLength": {
"20": null
},
"optionIn": {
"option1": null,
"option2": null,
"option3": null,
"option4": null
}
}
},
"password": {
"type": {
"string": null
},
"validation": {
"required": null,
"minLength": {
"6": null
},
"maxLength": {
"30": null
}
}
},
"date": {
"type": {
"date": null
}
}
}
然后我transform()
将该中间对象转换为最终形式。
const inputStr =
`- name
- type
- string
- validation
- required
- minLength
- 4
- maxLength
- 20
- optionIn
- option1
- option2
- option3
- option4
- password
- type
- string
- validation
- required
- minLength
- 6
- maxLength
- 30
- date
- type
- date`
let parseLimit = 1000;
function parse(lines, curIndent = 0) {
if (parseLimit-- < 0) throw "parseLimit exhausted";
if (lines.length === 0) return null;
const obj = {};
let parent = null;
let descendantLines = [];
[...lines, '>'.repeat(curIndent)].forEach(line => {
const indents = (line.match(/>/g) || []).length;
if (indents === curIndent) {
if (parent) {
obj[parent] = parse(descendantLines, curIndent + 1);
}
descendantLines = [];
parent = line.replace(/>/g, '');
} else if (indents > curIndent) {
descendantLines.push(line);
} else {
throw 'indents < curIndent';
}
});
return obj;
}
let transformLimit = 1000;
function transform(node) {
if (transformLimit-- < 0) throw "transformLimit exhausted";
const childKeys = Object.keys(node);
const leafChildKeys = childKeys.filter(childKey => {
return node[childKey] === null;
});
if (childKeys.length === leafChildKeys.length) {
//all leaf children
const values = childKeys.map(value => {
return isNaN(value)
? value
: +value;
});
return values.length === 1
? values[0]
: values;
} else { //not all leaf children
const newNode = {};
childKeys.forEach(childKey => {
if (leafChildKeys.includes(childKey)) {
//true
newNode[childKey] = true;
} else {
//recurs
newNode[childKey] = transform(node[childKey]);
}
});
return newNode;
}
}
function solve(str) {
const lines = str
.split('\n')
.map(line => line
.replace(/ /g, '>')
.replace('- ', '')
);
return transform(parse(lines));
}
console.log('input:\n', inputStr);
console.log('solution: ', solve(inputStr));