递归数组连接错误(JavaScript)
任务:给定一个递归数组连接错误(JavaScript),javascript,recursion,Javascript,Recursion,任务:给定一个foo(bar)格式的字符串,将括号内的字符串反转 我的解决方案有一个错误,我无法理解其原因 这是我的密码: const inputs = ["foo(bar)", "(bar)", "foo(bar)blim", "foo(foo(bar))blim", "foo(foo(bar)ddas)blim", "foo(foo(b(tu)ar)ddas)blim&quo
foo(bar)
格式的字符串,将括号内的字符串反转
我的解决方案有一个错误,我无法理解其原因
这是我的密码:
const inputs = ["foo(bar)", "(bar)", "foo(bar)blim", "foo(foo(bar))blim", "foo(foo(bar)ddas)blim", "foo(foo(b(tu)ar)ddas)blim"]
const expected = ["foorab", "rab", "foorabblim", "foobaroofblim", "foosaddbaroofblim", "foosaddbutaroofblim"]
function reverseParans(input) {
firstLeftParans = input.indexOf('(')
lastRightParans = input.lastIndexOf(')')
if (firstLeftParans == -1) {
if (lastRightParans > -1) {
return ['<MALFORMED>']
} else {
return input.reverse()
}
} else {
if (lastRightParans == -1) {
return ['<MALFORMED>']
} else {
left = input.slice(0, firstLeftParans)
right = input.slice(lastRightParans+1).slice()
middle = reverseParans(input.slice(firstLeftParans + 1, lastRightParans))
return [...left, ...middle, ...right].reverse()
}
}
}
function process(str) {
let input = str.split('');
let firstLeftParans = input.indexOf('(');
let lastRightParans = input.lastIndexOf(')');
if (firstLeftParans == -1 && lastRightParans == -1) {
return input
} else if ((firstLeftParans > -1 && lastRightParans == -1) || (lastRightParans > -1 && firstLeftParans == -1)) {
return "<MALFORMED>"
}
result = input.slice(0, firstLeftParans).concat(reverseParans(input.slice(firstLeftParans + 1, lastRightParans)), input.slice(lastRightParans + 1))
return result.join('')
}
我想我在进行递归调用时错误地改变了一个值,但我不确定在哪里。你搞乱了你的范围,因为你没有声明你的变量是
reversePans
的本地变量。修改后的代码可以工作:
const inputs = ["foo(bar)", "(bar)", "foo(bar)blim", "foo(foo(bar))blim", "foo(foo(bar)ddas)blim", "foo(foo(b(tu)ar)ddas)blim"]
const expected = ["foorab", "rab", "foorabblim", "foobaroofblim", "foosaddbaroofblim", "foosaddbutaroofblim"]
function reverseParans(input) {
let firstLeftParans = input.indexOf('(')
let lastRightParans = input.lastIndexOf(')')
if (firstLeftParans == -1) {
if (lastRightParans > -1) {
return ['<MALFORMED>']
} else {
return input.reverse()
}
} else {
if (lastRightParans == -1) {
return ['<MALFORMED>']
} else {
let left = input.slice(0, firstLeftParans)
let right = input.slice(lastRightParans+1).slice()
let middle = reverseParans(input.slice(firstLeftParans + 1, lastRightParans))
return [...left, ...middle, ...right].reverse()
}
}
}
function process(str) {
let input = str.split('');
let firstLeftParans = input.indexOf('(');
let lastRightParans = input.lastIndexOf(')');
if (firstLeftParans == -1 && lastRightParans == -1) {
return input
} else if ((firstLeftParans > -1 && lastRightParans == -1) || (lastRightParans > -1 && firstLeftParans == -1)) {
return "<MALFORMED>"
}
result = input.slice(0, firstLeftParans).concat(reverseParans(input.slice(firstLeftParans + 1, lastRightParans)), input.slice(lastRightParans + 1))
return result.join('')
}
const inputs=[“foo(bar)”,“(bar)”,“foo(bar)blim”,“foo(foo(bar))blim”,“foo(foo(bar)ddas)blim”,“foo(foo(b(tu)ar)ddas)blim”]
预期常数=[“foorab”、“rab”、“foorabblim”、“foobaroofblim”、“foosadbaroofblim”、“foosadbaroofblim”、“foosadbutaroofblim”]
功能反转面板(输入){
设firstLeftParans=input.indexOf('('))
设lastRightParans=input.lastIndexOf('))
if(firstLeftParans==-1){
如果(lastRightParans>-1){
返回['']
}否则{
返回input.reverse()
}
}否则{
如果(lastRightParans==-1){
返回['']
}否则{
设left=input.slice(0,firstlefts)
让right=input.slice(lastRightParans+1).slice()
设middle=reversePans(input.slice(firstLeftParans+1,lastRightParans))
返回[…左,…中,…右]。反转()
}
}
}
功能过程(str){
让输入=str.split(“”);
设firstLeftParans=input.indexOf('(');
设lastRightParans=input.lastIndexOf(');
if(firstLeftParans==-1&&lastRightParans==-1){
返回输入
}else if((firstLeftParans>-1&&lastRightParans==-1)| |(lastRightParans>-1&&firstLeftParans=-1)){
返回“”
}
结果=input.slice(0,firstLeftParans).concat(reverseParans(input.slice(firstLeftParans+1,lastRightParans)),input.slice(lastRightParans+1))
返回结果。连接(“”)
}
通过数学归纳法进行递归可以简化程序。下面的编号注释与代码中的编号相对应-
s
功能流程(s=”“)
{const l=s.indexOf(“(”/“左”)
常数r=s.lastIndexOf(“)”/“右”
如果(l==-1&&r===-1)
返回s//1
else if(l==-1 | r==-1)
返回“”//2
其他的
返回s.substring(0,l)//3
+反向(过程(s.子串(l+1,r)))
+s.r(r+1)
}
我们可以将反向定义为-
const reverse=(s=”“)=>
s、 长度
? 反向(s.substr(1))+s.substr(0,1)
: ""
const输入=
[“foo(bar)”、“(bar)”、“foo(bar)blim”、“foo(foo(bar))blim”、“foo(foo(bar)ddas)blim”、“foo(foo(b(tu)ar)ddas)blim”]
预期常数=
[“foorab”、“rab”、“foorabblim”、“foobaroofblim”、“foodsaddbaroofblim”、“foodsaddbutaroofblim”]
常数结果=
输入。映射(过程)//
s、 长度
? 反向(s.substr(1))+s.substr(0,1)
: ""
功能流程(s=”“)
{const l=s.indexOf(“”)
常数r=s.lastIndexOf(“)”)
如果(l==-1&&r===-1)
返回s
else if(l==-1 | r==-1)
返回“”
其他的
返回s.子字符串(0,l)
+反向(过程(s.子串(l+1,r)))
+s.r(r+1)
}
常量输入=
[“foo(bar)”、“(bar)”、“foo(bar)blim”、“foo(foo(bar))blim”、“foo(foo(bar)ddas)blim”、“foo(foo(b(tu)ar)ddas)blim”]
预期常数=
[“foorab”、“rab”、“foorabblim”、“foobaroofblim”、“foodsaddbaroofblim”、“foodsaddbutaroofblim”]
常数结果=
inputs.map(process)/当存在多组未列出的参数时,此问题的其他一些答案会产生错误的结果-
console.log(进程(“你好(世界)是(否)阳(阴)”)
//helloniy(gnaynosey)dlrow
控制台日志(过程(“ab(cd(ef(gh)))ij(k(lm)n)opqr(stu(vw)x)yz”))
//hgopqr(stu(vwdcyz
//哦,不!
lex
让我们尝试另一种解决问题的方法。首先,lexer
创建一个词素流-
function* lexer(s = "")
{ const leftParen =
{ type: "leftParen" }
const rightParen =
{ type: "rightParen" }
const str = value =>
({ type: "str", value })
let r =
""
for (const c of s)
if (c === "(")
(yield str(r), yield leftParen, r = "")
else if (c === ")")
(yield str(r), yield rightParen, r = "")
else
r = r + c
yield str(r)
}
让我们看看lexer
是如何工作的-
lexer(“这(是(非常(嵌套))但是(没有)”)/=>。。。
{type:“str”,value:“this”}
{type:“leftParen”}
{type:“str”,value:“is”}
{type:“leftParen”}
{类型:“str”,值:“very”}
{type:“leftParen”}
{类型:“str”,值:“嵌套”}
{type:“rightParen”}
{类型:“str”,值:}
{type:“rightParen”}
{类型:“str”,值:}
{type:“rightParen”}
{type:“str”,value:“but”}
{type:“leftParen”}
{类型:“str”,值:“nothere”}
{type:“rightParen”}
{类型:“str”,值:}
解析
接下来,parser
获取词素并生成一个抽象语法树-
函数解析器(词素)
{const concat=\=>
({类型:“concat”,值:[]})
const rev=\uu=>
({类型:“rev”,值:[]})
常数r=
[concat()]
for(词素常量)
如果(t.type==“str”)
r[0]。值。取消移位(t)
else if(t.type==“leftParen”)
r、 取消移位(rev())
else if(t.type==“rightParen”)
如果(r.长度1)
抛出错误(“预期“')”)
其他的
返回r[0]
}
现在让我们看看解析器的效果-
parser(lexer(“this(非常(嵌套)))但是(nothere)”)/=>。。。
{键入:“concat”
,价值观:
[{类型:“str”,值:}
,{类型:“rev”
,价值观:
[{type:“str”,value:“nothere”}
]
}
,{type:“str”,value:“but”},
{类型:“rev”
,价值观:
[{类型:“str”,值:}
,{类型:“rev”
价值
foorab, rab, foorabblim, foobaroofblim, foosaddbaroofblim, foosaddbutaroofblim
foorab, rab, foorabblim, foobaroofblim, foosaddbaroofblim, foosaddbutaroofblim
function* lexer(s = "")
{ const leftParen =
{ type: "leftParen" }
const rightParen =
{ type: "rightParen" }
const str = value =>
({ type: "str", value })
let r =
""
for (const c of s)
if (c === "(")
(yield str(r), yield leftParen, r = "")
else if (c === ")")
(yield str(r), yield rightParen, r = "")
else
r = r + c
yield str(r)
}
foorab, rab, foorabblim, foobaroofblim, foosaddbaroofblim, foosaddbutaroofblim
foorab, rab, foorabblim, foobaroofblim, foosaddbaroofblim, foosaddbutaroofblim
char = "a" | "b" | "c" | "d" ...
| "A" | "B" | "C" | "D" ...
| "1" | "2" | "3" | "4" ...
| "!" | "@" | "#" | "$" ...
| ...
string = ""
| char + string
expr = string
| expr + "(" + expr + ")" + expr