将嵌套列表转换为对象-Javascript

时间:2019-05-16 15:19:46

标签: javascript list object task generate

我们需要帮助来解决此问题,我们企业中没人能做到。

我们有一个像这样的字符串:

- 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值的对象

这是一项艰巨而复杂的任务,可以根据需要使用库。

1 个答案:

答案 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));