For a hobby-project I needed to indent an XML text which my code compiled and came up with a solution which is quite simple.
The input is an array with XML tags and all children nodes is nested inside other array.
A short example for that:
const input = [
'<!DOCTYPE html>',
'<html lang="en">',
[
'<head>',
[
'<title>Hello, World</title>',
],
'</head>',
'<body>',
[
'<h1>It works!</h1>',
],
'</body>',
],
'</html>',
];
And the output I wanted to achieve is this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello, World</title>
</head>
<body>
<h1>It works!</h1>
</body>
</html>
With the given input, the following code would achieve the goal:
function indentText (nodes) {
return Array.isArray(nodes)
? nodes.flatMap(indentText).map(node => '\t' + node)
: nodes;
}
const output = input
.flatMap(indentText)
.join('\n');
console.log(output);
Walk-through on the callback:
- A callback passed to the Array.prototype.flatMap will walk through all the items and expected to return an item or an array for flattening.
- If the passed value is not an array, it just returns it back - because we want to maintain the value.
- If it's an array, it's a whole other story: Because flatMap only works on the first level, the method calls itself recursively through flatMap to resolve the deeper layers.
- The recursive call makes sure there will be no arrays inside the actual one, just text (assuming the input is correct)
- Mapping the items and adding an indent prefix to them. On the deepest level it will add a single character on each item, which will be accumulated during the recursive call going up the levels
Top comments (3)
Neat idea! I don't think I've ever used flatmap in this way - but will definitely think about it next time I have to recurse through something like this. Thanks :)
Thanks for the kind words! :)
This was a breakthrough for me: Previously I didn't understand how flatMap works, but when I thought about the problem it just *clicked* and I knew this will work flawlessly :))
I love that feeling! It makes learning new things addicting :)