英文:
How can I bypass the object to get the specific data?
问题
I see that you're trying to create a function to format the input data into a specific tree-like structure in JavaScript. Based on your code and the desired output, it looks like you want to format the data based on the "type" property in each object within the input data. Here's the corrected code:
const stylish = (data, replacer = ' ', spacesCount = 1) => {
const iter = (data, depth) => {
const arr = [];
const keys = Object.keys(data);
const sizeBefore = depth * spacesCount;
const replacerBefore = replacer.repeat(sizeBefore);
keys.forEach((key) => {
if (data[key].type === 'object') {
arr.push(`${replacerBefore}${key} : {\n${iter(data[key].value, depth + 1)}\n${replacerBefore}}`);
} else if (data[key].type === 'added') {
arr.push(`${replacerBefore}+ ${key} : ${iter(data[key].value, depth)}`);
} else if (data[key].type === 'deleted') {
arr.push(`${replacerBefore}- ${key} : ${iter(data[key].value, depth)}`);
} else if (data[key].type === 'changed') {
arr.push(`${replacerBefore}- ${key} : ${data[key].value1}`);
arr.push(`${replacerBefore}+ ${key} : ${data[key].value2}`);
} else if (data[key].type === 'nochanged') {
arr.push(`${replacerBefore}${key} : ${data[key].value2}`);
}
});
return arr.join('\n');
};
return `{\n${iter(data, 1)}\n}`;
};
You can call the stylish
function with your input data to get the desired output:
const inputData = // Your input data here;
const formattedData = stylish(inputData);
console.log(formattedData);
This should produce the output you specified in your original request.
英文:
I have a object with values: { key: '', value: '', type: '' }. I need to realize formatter, which output tree from input data in output data. Please help me, because i can`t understand how i can do it, and please explain the answer. Please if you know any books or sites where i can understand objects, arrays, js. Thanks very much.
INPUT data:
const el = [
{
"key": "common",
"value": [
{
"key": "follow",
"value": false,
"type": "added"
},
{
"key": "setting1",
"value1": "Value 1",
"value2": "Value 1",
"type": "nochanged"
},
{
"key": "setting2",
"value": 200,
"type": "deleted"
},
{
"key": "setting3",
"value1": true,
"value2": null,
"type": "changed"
},
{
"key": "setting4",
"value": "blah blah",
"type": "added"
},
{
"key": "setting5",
"value": {
"key5": "value5"
},
"type": "added"
},
{
"key": "setting6",
"value": [
{
"key": "doge",
"value": [
{
"key": "wow",
"value1": "",
"value2": "so much",
"type": "changed"
}
],
"type": "object"
},
{
"key": "key",
"value1": "value",
"value2": "value",
"type": "nochanged"
},
{
"key": "ops",
"value": "vops",
"type": "added"
}
],
"type": "object"
}
],
"type": "object"
},
{
"key": "group1",
"value": [
{
"key": "baz",
"value1": "bas",
"value2": "bars",
"type": "changed"
},
{
"key": "foo",
"value1": "bar",
"value2": "bar",
"type": "nochanged"
},
{
"key": "nest",
"value1": {
"key": "value"
},
"value2": "str",
"type": "changed"
}
],
"type": "object"
},
{
"key": "group2",
"value": {
"abc": 12345,
"deep": {
"id": 45
}
},
"type": "deleted"
},
{
"key": "group3",
"value": {
"deep": {
"id": {
"number": 45
}
},
"fee": 100500
},
"type": "added"
}
]
OUTPUT data:
{
common: {
+ follow: false
setting1: Value 1
- setting2: 200
- setting3: true
+ setting3: null
+ setting4: blah blah
+ setting5: {
key5: value5
}
setting6: {
doge: {
- wow:
+ wow: so much
}
key: value
+ ops: vops
}
}
group1: {
- baz: bas
+ baz: bars
foo: bar
- nest: {
key: value
}
+ nest: str
}
- group2: {
abc: 12345
deep: {
id: 45
}
}
+ group3: {
deep: {
id: {
number: 45
}
}
fee: 100500
}
}
I tried call function with recursive, but i don`t know what do next.
const stylish = (data, replacer = ' ', spacesCount = 1) => {
const iter = (data, depth) => {
const arr = [];
const keys = Object.keys(data);
const sizeBefore = depth * spacesCount;
const replacerBefore = replacer.repeat(sizeBefore);
keys.forEach((key) => {
if (data[key].type === 'object') {
arr.push(`${replacerBefore} ${data[key].key} : ${iter(data[key].value)}`);
} if (data[key].type === 'added') {
arr.push(`${replacerBefore}+ ${data[key].key} : ${iter(data[key].value)}`);
} if (data[key].type === 'deleted') {
arr.push(`${replacerBefore}- ${data[key].key} : ${iter(data[key].value)}`);
} if (data[key].type === 'changed') {
arr.push(`${replacerBefore}- ${data[key].key} : ${data[key].value1}`);
arr.push(`${replacerBefore}+ ${data[key].key} : ${data[key].value2}`);
} if (data[key].type === 'nochanged') {
arr.push(`${replacerBefore} ${data[key].key} : ${data[key].value2}`);
}
});
return [
'{',
...arr,
'}'
].join('\n');
};
What i get with my code:
Output:
{
common : {
+ follow : {
}
setting1 : Value 1
- setting2 : {
}
- setting3 : true
+ setting3 : null
+ setting4 : {
}
+ setting5 : {
}
setting6 : {
doge : {
- wow :
+ wow : so much
}
key : value
+ ops : {
}
}
}
group1 : {
- baz : bas
+ baz : bars
foo : bar
- nest : [object Object]
+ nest : str
}
- group2 : {
}
+ group3 : {
}
}
答案1
得分: 0
处理复杂数据结构时,只需将不同类型的元素的处理分开,以便可以使用专用逻辑处理每种类型。
在您的情况下,有objects
描述了对结构的更改。还有contents
,它是这些更改的原始负载。
所以当遇到object
时,嵌套项可以是object
和content
(字母是除了"type": "object"
之外的每个条目)。使用相应的例程进一步处理它们。
当遇到content
时,它要么是可以直接写入输出的原始值,要么是Array
或Object
的实例,其项基本上是嵌套的contents
。
显然,为了保持正确的缩进,需要在处理的每一点跟踪当前嵌套级别。
英文:
When dealing with complex data structures, just separate processing of different types of elements so that you can handle each type with dedicated logic.
In your case you have objects
which describe changes to the structure. And you have contents
which is a raw payload of those changes.
So when you encounter object
, nested items can be both object
and content
(the letter is every entry that is not "type": "object"
). Process them further with corresponding routines.
And when you encounter content
, it is either a primitive value that can be written to the output as is; or it is an instance of Array
or Object
whose items are basically nested contents
.
Obviously, in order to maintain proper indenting, it is necessary to keep track of the current nesting level at every point of processing.
I did this demo for the sake of practice. It can detect errors in the structure and add them to the output (first call) or silently skip (second call).
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const input = [
{
"key": "common",
"value": [
{
"key": "follow",
"value": false,
"type": "added"
},
{
"key": "setting1",
"value1": "Value 1",
"value2": "Value 1",
"type": "nochanged"
},
{
"key": "setting2",
"value": 200,
"type": "deleted"
},
{
"key": "setting3",
"value1": true,
"value2": null,
"type": "changed"
},
{
"key": "setting4",
"value": "blah blah",
"type": "added"
},
{
"key": "setting5",
"value": { "key5": "value5" },
"type": "added"
},
{
"key": "setting6",
"value": [
{
"key": "doge",
"value": [
{
"key": "wow",
"value1": "",
"value2": "so much",
"type": "changed"
}
],
"type": "object"
},
{
"key": "key",
"value1": "value",
"value2": "value",
"type": "nochanged"
},
{
"key": "ops",
"value": "vops",
"type": "added"
}
],
"type": "object"
}
],
"type": "object"
},
{
"key": "group1",
"value": [
{
"key": "baz",
"value1": "bas",
"value2": "bars",
"type": "changed"
},
{
"key": "foo",
"value1": "bar",
"value2": "bar",
"type": "nochanged"
},
{
"key": "nest",
"value1": { "key": "value" },
"value2": "str",
"type": "changed"
}
],
"type": "object"
},
{
"key": "group2",
"value": { "abc": 12345, "deep": { "id": 45 } },
"type": "deleted"
},
{
"key": "group3",
"value": { "deep": { "id": { "number": 45 } }, "fee": 100500 },
"type": "added"
},
{
"key": "RIDICULOUSLY-NESTED-ARRAY",
"value1": [[[[[['BOOM!']]]]]],
"value2": [[[[[['BOOM!']]]]]],
"type": "nochanged"
},
{
"key": "CUSTOM-OBJECT",
"value": {
"EMPTY-OBJECT": {},
"EMPTY-ARRAY": [],
"ARRAY-OF-PRIMITIVES": [ 100, 200, 300 ],
"ARRAY-OF-ARRAYS": [
[ "Alice", "Bob" ],
[ "Kent", "Jessica" ]
],
"ARRAY-OF-OBJECTS": [
{ "aaa": 111, "bbb": 222, "ccc": 333 },
{ "ddd": 444, "eee": 555, "fff": 666 }
],
"COMPLEX-ARRAY": [
"next item is empty array", [],
"next item is empty object", {},
{
"ggg": { "YES": "NO" },
"hhh": [ true, false ],
"iii": 10000000000000000111111110222203333n
},
null
]
},
"type": "added"
},
"INVALID ENTRY",
{
"key": ["INVALID KEY"]
},
{
"key": "TEST-INVALID-TYPE",
"type": "INVALID TYPE"
},
{
"key": "TEST-INVALID-OBJECT",
"value": "INVALID OBJECT",
"type": "object"
},
{
"key": "TEST-EMPTY-OBJECT",
"value": [],
"type": "object"
}
];
function stylish (input, includeErrors) {
function writeNewline (string, level, sign) {
output += sign
? `\n${' '.repeat(level - 1)} ${sign} ${string}`
: `\n${' '.repeat(level)}${string}`;
}
function writeError (message, level) {
if (level) {
writeNewline(`ERROR: ${message}`, level, '!');
}
else {
output += `ERROR: ${message}`;
}
}
function writeNested (brackets, level, callback) {
output += brackets[0];
let savedLength = output.length;
callback();
if (savedLength == output.length) {
output += brackets[1];
}
else {
writeNewline(brackets[1], level);
}
}
function processContent (input, level) {
if (Array.isArray(input)) {
writeNested('[]', level, () => {
input.forEach((item) => {
writeNewline('', level + 1);
processContent(item, level + 1);
});
});
}
else if (typeof input == 'object' && input != null) {
writeNested('{}', level, () => {
Object.entries(input).forEach(([key, value]) => {
writeNewline(key + ': ', level + 1);
processContent(value, level + 1);
});
});
}
else {
output += input;
}
}
function processObjectEntry (input, level) {
if (typeof input == 'object' && input != null) {
let key = input.key;
if (typeof key != 'string') {
if (includeErrors) {
writeError('invalid <key> of entry', level);
}
return;
}
let prefix = key + ': ';
switch (input.type) {
case 'object':
if (Array.isArray(input.value)) {
writeNewline(prefix, level);
processObject(input.value, level);
}
else if (includeErrors) {
writeError(`entry "${key}" -> <value> has to be an array`, level);
}
break;
case 'added':
writeNewline(prefix, level, '+');
processContent(input.value, level);
break;
case 'deleted':
writeNewline(prefix, level, '-');
processContent(input.value, level);
break;
case 'changed':
writeNewline(prefix, level, '-');
processContent(input.value1, level);
writeNewline(prefix, level, '+');
processContent(input.value2, level);
break;
case 'nochanged':
writeNewline(prefix, level);
processContent(input.value1, level);
break;
default:
if (includeErrors) {
writeError(`entry "${key}" -> invalid <type>`, level);
}
}
}
else if (includeErrors) {
writeError('entry has to be an object', level);
}
}
function processObject (input, level) {
writeNested('{}', level, () => {
input.forEach((item) => processObjectEntry(item, level + 1));
});
}
let output = '';
if (Array.isArray(input)) {
processObject(input, 0);
}
else if (includeErrors) {
writeError('input has to be an array');
}
return output;
}
console.log(stylish(input, true));
console.log(stylish(input));
<!-- language: lang-css -->
.as-console-wrapper { max-height: 100% !important; }
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论