JavaScript(ES6),221
返回字符串数组的非递归函数(仍在内部使用递归子函数)
a=>[...(R=(a,l)=>a[r[l]='',0]&&a[0].map?'O'+a.map(v=>R(v,l+1))+'C':a.join` `)([a],l=-1,r=[],m='')].map(c=>r=r.map(x=>x+v[(k<0)*2+!k--],k=l,1/c?v='-- ':(v='-+|',c>'C'?k=++l:c>','&&--l,c='|'),m+=c))&&[...r,m,...r.reverse()]
这将分两步进行。
步骤1:以递归方式构建嵌套输入数组的字符串表示形式。例:
[[[1, 2, 3], [],[4, 5]], [6, 7, 8]]
-> "OOO1 2 3,,4 5C,6 7 8CC"
O
并C
标记打开和关闭子数组。简单的数字子数组以元素之间用空格分隔的方式呈现,而如果数组成员是子数组,则它们之间用逗号分隔。该字符串跟踪输入数组的多级结构,而我可以得到输出的中间行,只需将其替换OC,
为即可|
。在递归构建此临时字符串时,我还找到了最大深度级别并初始化了一个空字符串数组,该数组将包含输出的上半部分。
注意:外部框是棘手的,我将输入嵌套在另一个外部数组中,然后删除不需要的输出的第一行
步骤2:扫描临时字符串并构建输出
现在,我有一个空字符串数组,每个级别一个。我扫描临时字符串,跟踪当前级别,该级别每个增加,每个O
减小C
。我像这样想象:
[[[1, 2, 3], [],[4, 5]], [6, 7, 8]]
OOO1 2 3,,4 5C,6 7 8CC
+ +
+ + +
+ ++ +
|||1 2 3||4 5||6 7 8||
上升和下降遵循当前水平
对于每个字符,我遵循以下规则在输出的每一行中添加一个字符:
-如果是数字或空格,请在当前级别及以下放置一个“-”,在其上方放置一个空格
-否则,在该位置放置一个“ +”当前级别,如果在下面,则添加“-”,然后添加“ |” 如果以上
OOO1 2 3,,4 5C,6 7 8CC
+--------------------+
|+------------+-----+|
||+-----++---+| ||
|||1 2 3||4 5||6 7 8||
在临时扫描期间,我还建立了中间行,替换OC,
为|
在此步骤的最后,我有上半部分和中间一行,我只需要镜像顶部即可得到下半部分,然后就完成了
少打高尔夫球,注释代码
a=>{
r = []; // output array
R = ( // recursive scan function
a, // current subarray
l // current level
) => (
r[l] = '', // element of r at level r, init to ""
a[0] && a[0].map // check if it is a flat (maybe empty) array or an array of arrays
? 'O'+a.map(v=>R(v,l+1))+'C' // mark Open and Close, recurse
: a.join` ` // just put the elements space separated
);
T = R([a],-1)]; // build temp string
// pass the input nested in another array
// and start with level -1 , so that the first row of r will not be visible to .map
// prepare the final output
m = '' // middle row, built upon the chars in T
l = -1 // starting level
[...T].map(c => // scan the temp string
{
k = l; // current level
1/c // check if numeric or space
? v = '-- ' // use '-','-',' '
: (
v = '-+|', // use '-','+','|'
c > 'C'
? k=++l // if c=='O', increment level and assign to k
: c>'A'&&--l, // if c=='C', decrement level (but k is not changed)
c='|' // any of O,C,comma must be mapped to '|'
);
m += c; // add to middle row
r = r.map( (x,i) => // update each output row
// based on comparation between row index and level
// but in golfed code I don't use the i index
// and decrement l at each step
x + v[(k<i)*2+!(k-i)]
)
})
// almost done!
return [...r,m,...r.reverse()]
)
测试
F=
a=>[...(R=(a,l)=>a[r[l]='',0]&&a[0].map?'O'+a.map(v=>R(v,l+1))+'C':a.join` `)([a],l=-1,r=[],m='')].map(c=>r=r.map(x=>x+v[(k<0)*2+!k--],k=l,1/c?v='-- ':(v='-+|',c>'C'?k=++l:c>','&&--l,c='|'),m+=c))&&[...r,m,...r.reverse()]
out=x=>O.textContent = x+'\n'+O.textContent
;[[1,2,3]
,[[[1, 2, 3], [4, 5]], [6, 7, 8]]
,[]
,[[], []]
,[[], [1], [], [2], [], [3], []]
,[[[[[0]]]]]
,[[[[[4, 3, 2, 1]]]], [[[3, 2, 1]]], [[2, 1]], [1]]
].forEach(t=>
out(JSON.stringify(t)+'\n'+F(t).join`\n`+'\n')
)
function update()
{
var i=eval(I.value)
out(JSON.stringify(i)+'\n'+F(i).join`\n`+'\n')
}
update()
#I { width:90%}
<input id=I value='[[[1, 2, 3], [],[4, 5]], [6, 7, 8]]' oninput='update()'>
<pre id=O></pre>