不使用全局变量的递归算法的返回值
问题描述:
编写一个返回某个activity
的name
的算法。不使用全局变量的递归算法的返回值
在我们的功能,我们给出activity
的价值,如果我们的数组中存在返回name
的价值:
例子:
findMatch('scuba diving', activityItems) = 'Beach'
const activityItems = [
{
name: 'Sunday',
items: [
{
name: 'Gym',
activity: 'weights',
},
],
},
{
name: 'Monday',
items: [
{
name: 'Track',
activity: 'race',
},
{
name: 'Work',
activity: 'meeting',
},
{
name: 'Swim',
items: [
{
name: 'Beach',
activity: 'scuba diving',
},
{
name: 'Pool',
activity: 'back stroke',
},
],
},
],
},
{} ...
{} ...
];
我的实现:
let match = '';
const findMatch = (activity, activityItems) => {
for (let i = 0; i < activityItems.length; i += 1) {
if (activityItems[i].activity === activity) {
match = activityItems[i].name;
return match;
}
if (activityItems[i].items && findMatch(activity, activityItems[i].items)) {
return match;
}
}
return false;
};
但是我不喜欢我的实现,因为使用了一个全局变量。有没有方法可以在没有它的情况下返回正确的值?
我试过的东西:
const findMatch = (activity, activityItems) => {
for (let i = 0; i < activityItems.length; i += 1) {
if (activityItems[i].activity === activity) {
return activityItems[i].name;
}
if (activityItems[i].items) {
return findMatch(activity, activityItems[i].items);
}
}
return false;
};
但这总是返回false或未定义。
有什么建议吗?
答
为什么要把这个全局变量放在第一位?只要返回名称,如果它存在,或者如果不存在,则返回null
。请将导致当地变量的递归搜索,并且只返回如果不是null
:
const findMatch = (activity, activityItems) => {
for (let i = 0; i < activityItems.length; i++) {
if (activityItems[i].activity === activity)
return activityItems[i].name;
if (activityItems[i].items) {
let match = findMatch(activity, activityItems[i].items);
if (match) return match;
}
}
return null;
};
答
在Array.prototype.find
方法内建当发现没有值返回undefined
,所以我为榜样通过使用undefined
作为不匹配结果。
我也会用for of
来实现你的功能。
const activityItems = [
{name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]},
{name: 'Monday',items: [{name: 'Track',activity: 'race'},
{name: 'Work',activity: 'meeting'},
{name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'},
{name: 'Pool',activity: 'back stroke'}]}]},
{},
{}
];
const findMatch = (needle, haystack) => {
for (let {activity, name, items} of haystack) {
if (activity == needle) return name;
if (items && (items = findMatch(needle, items))) return items;
}
return undefined;
}
console.log(findMatch('scuba diving', activityItems))
这也采用解构assingment在for of
环抓住你想要的特定属性。我重用了items
变量来分配递归调用的结果。您不需要这样做,但它可以缩短一点,而不必为此目的而声明变量。
下面是使用.reduce()
,以帮助满足棉短绒一个版本,但现在我们已经失去了短路:-(。
const activityItems = [
{name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]},
{name: 'Monday',items: [{name: 'Track',activity: 'race'},
{name: 'Work',activity: 'meeting'},
{name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'},
{name: 'Pool',activity: 'back stroke'}]}]},
{},
{}
];
const findMatch = (needle, haystack) => {
return haystack.reduce((res, {activity, name, items}) =>
res !== undefined ? res :
activity == needle ? name :
items && findMatch(needle, items)
, undefined)
}
console.log(findMatch('scuba diving', activityItems))
还有一个版本,使用功能性技术,而不使用内置的方法。如果功能性编码是你以后的,我会采用这种方法。
const activityItems = [
{name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]},
{name: 'Monday',items: [{name: 'Track',activity: 'race'},
{name: 'Work',activity: 'meeting'},
{name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'},
{name: 'Pool',activity: 'back stroke'}]}]},
{},
{}
];
const findMatch = (needle, haystack) => {
if (!haystack || !haystack.length) {
return undefined;
}
const {activity, name, items} = haystack[0];
return activity == needle ? name :
findMatch(needle, items) || findMatch(needle, haystack.slice(1));
}
console.log(findMatch('scuba diving', activityItems))
OK,多一个。这是最后一个小变化。由于我们正在讨论使用尾递归的纯粹函数式编程,因此定义将头部与尾部分开的参数非常有用。 传播语法和其余语法使这个很容易。
const activityItems = [
{name: 'Sunday',items: [{name: 'Gym',activity: 'weights'}]},
{name: 'Monday',items: [{name: 'Track',activity: 'race'},
{name: 'Work',activity: 'meeting'},
{name: 'Swim',items: [{name: 'Beach',activity: 'scuba diving'},
{name: 'Pool',activity: 'back stroke'}]}]},
{},
{}
];
const findMatch = (needle, head, ...tail) => {
if (!head) {
return undefined;
}
const {activity, name, items} = head;
return activity == needle ? name :
items && findMatch(needle, ...items) || findMatch(needle, ...tail);
}
console.log(findMatch('scuba diving', ...activityItems))
eslint错误:'迭代器/发电机需要蓄冷器运行时,这也太重量级本指南,使他们。另外,应该避免使用循环来支持数组迭代no-restricted-syntax' – user2456977
+ eslint:由于活动和名称未被重新分配,因此更改开销。然后我添加另一个变量,而不是重复使用物品..然后得到错误 – user2456977
以上所以必须有一个转译参与?什么“指南”不允许他们,为什么?使用转译器的关键是现在能够使用有用的新语法功能,而不是为了避免它们。 “无限制语法”配置表达的意见远非绝对。我将在一周中的任何一天使用'for for'数组迭代方法。我想我可以重写这个使用'.reduce()',但我没有看到任何收益。 – llama