我试图从递归调用中返回一个字符串然后对其进行切片,但切片的行为很奇怪。
鉴于
let first = arr => arr.slice(0, 1)
let rest = arr => arr.slice(1)
let join = function join(arr, connector) {
return !arr.length ? '' : first(arr) + connector + join(rest(arr), connector)
}
let nums = [1, 2, 34, 45, 100]
其中join从数组值创建一个字符串,并使用连接符
join(nums, '-')
返回
"1-2-34-45-100-"
然后切掉最后一个' - '
"1-2-34-45-100-".slice(0, -1)
返回
"1-2-34-45-100"
或
function f() {
return ("1-2-34-45-100-").slice(0, -1)
}
f()
返回 " 1-2-34-45-100"
足够简单。那么为什么在上面的递归调用的结果中添加一个切片,比如
let join = function join(arr, connector) {
return ( !arr.length ? '' : first(arr) + connector + join(rest(arr), connector) )
.slice(0, -1);
}
产生这个吗?
join(nums, '-')
// -> "1-2-34-45"
// shouldn't this be "1-2-34-45-100" ?
甚至是陌生人,
join([1,2,3,4,5,6,7,8,9,10], '-')
// -> "1-2-3-4-5-6"
切片是否涉及递归调用?
答案 0 :(得分:1)
首先,您的first
功能
// first :: [a] -> [a] WUPS
let first = arr =>
arr.slice(0, 1)
first
应该返回第一个元素,不是包含第一个项目的单个元素数据
// first :: [a] -> a
const first = xs =>
xs[0]
接下来,我们考虑一下函数的完整domain(输入)。您的函数接受一个字符串数组。该数组可以包含0,1或更多字符串,我们需要您的函数适用于所有情况 - codomain(输出)是字符串类型; join
应始终返回字符串
// contract
join ([]) == ''
join ([a]) == a
join ([a,b]) == a + '-' + b
join ([a,b,c]) == a + '-' + b + '-' + c
在JavaScript中将其编码为递归函数是微不足道的 - 请注意,不需要跟踪数组索引或担心增加迭代器 - 只需考虑履行合同
const first = xs =>
xs[0]
const rest = xs =>
xs.slice (1)
const join = xs => {
switch (xs.length) {
case 0: return ''
case 1: return first (xs)
default: return first (xs) + '-' + join (rest (xs))
}
}
console.log (join ([])) // ''
console.log (join (['a'])) // 'a'
console.log (join (['a', 'b'])) // 'a-b'
console.log (join (['a', 'b', 'c'])) // 'a-b-c'

当然,如果我们允许用户指定加入字符串
,我们的功能可以大大改进
const first = xs =>
xs[0]
const rest = xs =>
xs.slice (1)
const join = (y, xs) => {
switch (xs.length) {
case 0: return ''
case 1: return first (xs)
default: return first (xs) + y + join (y, rest (xs))
}
}
console.log (join ('&', [])) // ''
console.log (join ('&', ['a'])) // 'a'
console.log (join ('&', ['a', 'b'])) // 'a&b'
console.log (join ('&', ['a', 'b', 'c'])) // 'a&b&c'

答案 1 :(得分:0)
每次运行slice
时,将slice
置于连接函数中都会导致join()
。
因为你在连接函数中进行递归,所以slice
将被多次调用。
尝试在完成join()
时调用切片。它会起作用。
let first = arr => arr.slice(0, 1)
let rest = arr => arr.slice(1)
let join = function join(arr, connector) {
return ( !arr.length ? '' : first(arr) + connector + join(rest(arr), connector) )
}
join([1,2,3,4,5,6,7,8,9,10], '-').slice(0, -1)
根据您的顾虑,您可以这样编写代码:
const join = function(arr, connector) {
const first = arr => arr.slice(0, 1)
const rest = arr => arr.slice(1)
const joinChain = function(arr, connector) {
return ( !arr.length ? '' : first(arr) + connector + joinChain(rest(arr), connector) );
}
return joinChain(arr, connector).slice(0, -1);
}
join([1,2,3,4,5,6,7,8,9,10], '-')
答案 2 :(得分:0)
您应该只调整逻辑以避免尾随连接器。
extension myEnum {
var description: String {
let mirror = Mirror(reflecting: self)
var result = ""
for child in mirror.children {
if let label = child.label {
result += "\(label): \(child.value)"
} else {
result += "\(child.value)"
}
}
return result
}
}

A"休息参数"在嵌套函数上可以使这更简单。
let first = arr => arr.slice(0, 1)
let rest = arr => arr.slice(1)
let join = function join(arr, conn) {
return !arr.length ? "" :
first(arr) + (arr.length === 1 ? "" : (conn + join(rest(arr), conn)))
}
let nums = [1, 2, 34, 45, 100]
console.log(join(nums, "-"));