我正在从事JavaScript练习,但在弄清逻辑为何起作用时遇到了一些麻烦。它基本上具有一个称为“神秘”的函数,该函数使用许多非常简单的函数,并以相反的顺序返回您提供的数组。我已经在白板前坐了一个小时,试图弄清楚背后的逻辑,但没有理解。善良的灵魂可以看看这些功能并解释神秘功能如何返回反向数组吗?谢谢!
LinkListControlToField1.Active := true;
答案 0 :(得分:2)
神秘是一个递归函数。
它使用rest
函数的返回值进行自身调用,该函数返回除第一个元素以外的所有内容。
它使用that的结果+ first
的结果,该结果返回第一个字符,并再次连接它们(使用conj
),但第一个元素结尾。
所以,假设您输入了[H e l l o],
它将返回conj(mystery([e l l o], H)
mystery([e l l o])
将返回conj(mystery([l l o], e)
mystery([l l o])
将返回conj(mystery([l o], l)
依此类推,直到进入mistery
的数组为空,在这种情况下递归结束,然后我们冒泡回到第一个调用。
请注意,递归经常用于这样的练习,但是尽管它有一些特定的用途,但在许多情况下,不使用递归会更有效,因为与调用该函数相比,进行另一个函数调用的开销相对比较大。其他解决方案使用一个简单的循环来移动或交换项目。
如果您输出一些信息,您可以看到正在发生的事情:
function rest(arr) {
return arr.slice(1);
}
function first(arr) {
return arr[0];
}
function conj(arr, value) {
arr.push(value);
return arr;
}
function mystery(array, level) {
if (array.length === 0) {
console.log('mystery level '+level+' is called with an empty array. Recursion ends here.. Stay tuned for the answer.');
return [];
}
console.log('mystery level '+level+' is called with '+array+
'. I will move '+first(array)+' to the end.');
var result = conj(mystery(rest(array), level+1), first(array));
console.log('returning '+result+' for level '+level);
return result;
}
console.log(mystery(['H','e','l','l','o'], 0));
答案 1 :(得分:1)
要了解使用递归的函数,可以暂时假设 recursive (嵌套)调用返回其应有的内容,然后查看其构建方式从而产生正确的结果。
例如,假设array
是[1, 2, 3, 4]
所以这行:
conj(mystery(rest(array)), first(array));
...的递归调用为mystery
。它以array
作为参数,但是删除了第一个元素(即rest
返回的内容),因此它得到了[2, 3, 4]
现在,我们仅假设对mystery
的递归调用做正确的事情并将该数组反转为[4, 3, 2]
。然后,在上面引用的代码中,我们看到此结果与first(array)
(这是第一个值,即1)连接在一起。这样我们得到[4, 3, 2, 1]
。正确!
这告诉我们,如果我们假设mystery
对具有n-1个值的数组执行正确的工作,那么对n个值也适用。
现在需要看看mystery
是否能正确处理最小的情况,即数组为空。在这种情况下,很容易看到它返回了正确的结果,即一个空数组。
因此,将这两件事放在一起,您会发现mystery
对于所有可能的数组大小都能正确完成工作。
答案 2 :(得分:1)
您的第一个函数“ rest”将删除第一个元素,因为slice将把元素从1返回到数组的末尾,然后“ conj”函数将采用被删除的第一个元素(通过“ first”函数)并将其放在最后,然后递归执行,它将从一开始就将元素放到最后。
答案 3 :(得分:1)
.push
方法将该项放置在数组的末尾。
.slice(1)
的意思是“第一项除外”
mystery
的arg)。如果为空,则返回rest
(除第一个以外的所有东西)。我们将其余的称为B conj
=将value
附加到arr
first
=获得arr
的第一项
rest
=返回除第一项以外的所有内容
mystery
当array
为空时=返回空数组
mystery
,当array
不为空时=取rest(array)
,对其运行mystery
,然后附加数组first
答案 4 :(得分:1)
是的,递归的魔力。要理解,想一想如果您用2元素数组mystery
调用[1,2]
会做什么。
rest(array)
将是[2]
mystery(rest(array))
还将是[2]
first(array)
将是1
。
然后您返回conj([2], 1)
,这会导致[2,1]
。
现在的诀窍是递归。如果您有3个元素[0,1,2]
并用它来称呼奥秘,那就会发生:
mystery(rest(array))
,其本质上是mystery([1,2])
。我们已经看到了返回[2,1]
的结果。first(array)
将是0
conj([2,1],0)
,逻辑上是[2,1,0]
。现在,它可以根据需要为任意多个元素提供支持。本质上,每个元素都将调用mystery
,以将其放置在所有元素之后。
答案 5 :(得分:1)
这里要注意的一件事是mystery()
是递归调用的。我添加了一些注释来说明每个步骤的进展。
function rest(arr) {
console.log('take first n-1 elements of', arr);
return arr.slice(1);
}
function first(arr) {
return arr[0];
}
function conj(arr, value) {
arr.push(value);
console.log('combine', arr, 'with', value)
return arr;
}
function mystery(array) {
console.log('call mystery on ', array)
if (array.length === 0) {
return [];
}
return conj(mystery(rest(array)), first(array));
}
mystery([0,1,2])
答案 6 :(得分:1)
这很简单。您无法看到它的原因是 RECURSION 。我希望您注意几件事:
在这里,我将不讨论递归函数,而是向您展示如何使用 console.log()跟踪每个递归调用。在下面查看我的代码,我添加了console.log()以使您更加清楚。尝试运行一些数组的奥秘并查看结果。这对您来说很有意义。
function rest(arr) {
return arr.slice(1);
}
function first(arr) {
console.log("Returning ",arr[0], "from first(arr).")
return arr[0];
}
function conj(arr, value) {
console.log("Pushing ",value, " to ",arr, " in conj(arr,value)");
arr.push(value);
console.log("Returning ",arr, " from Conj(arr,value)");
return arr;
}
function mystery(array) {
if (array.length === 0) {
console.log("array is emplty. So, returning empty array from mystery");
return [];
}
console.log("array is not emplty. So, calling mystery(array) again.");
return conj(mystery(rest(array)), first(array));
}
var reverse =mystery([1,2,3,4]);
console.log("The final result", reverse);
答案 7 :(得分:0)
不会说谎,这是一种颠倒数组顺序的怪异方法。它基本上是使用递归来对数组的第一个元素进行切片,并将元素与最后一个元素合并在一起。
所以这里是散步:
mystery(['h','e','l','l','o'])
->
首先检查数组是否为空,然后调用方法rest
->
rest(['h','e','l','l','o'])
->
rest将索引1处的数组切成片,返回['e','l','l','o']
->
然后调用mystery
,它以返回值rest
->
mystery(['e','l','l','o'])
->
这意味着直到rest
返回一个空数组->
mystery(['e','l','l','o'])
->
mystery(['l','l','o'])
->
mystery(['l','o'])
->
mystery(['o'])
->
mystery([])
->
当谜题有一个空数组时,它将返回该空数组,然后将first
称为->
首先返回数组的第一个元素,并在返回神秘值之后发生,在返回神秘值之前它看起来像这样->
mystery(['e','l','l','o']) , first(['h','e','l','l','o'])
->
因此,在最低级别,当mystery返回一个空数组并首先返回['o']
中的第一个元素时,它看起来像这样->
[] , ['o']
->
conj
将使用这些值->
conj([] , ['o'])
->
conj
返回两个值的组合->
conj([] , ['o'])
->
['o']
->
然后返回并重复->
conj([] , ['o'])
->
conj(['o'] , ['l'])
->
conj(['o','l'] , ['l'])
->
conj(['o', 'l','l'] , ['e'])
->
conj(['o', 'l','l', 'e'] , ['h'])
->
['o', 'l','l', 'e','h']