编写一个返回某个name
的{{1}}的算法。
在我们的函数中,我们得到activity
的值,如果它存在于我们的数组中,则返回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;
};
但这总是返回false或undefined。
有什么建议吗?
答案 0 :(得分:1)
为什么要保留这个全局变量?只需返回名称(如果存在),或null
(如果不存在)。将递归搜索的结果保存在 local 变量中,只有在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;
};
时才返回:
android:visibleToInstantApps="true"
答案 1 :(得分:1)
当没有找到任何值时,内置的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))
这也使用for of
循环中的解构分配来获取您想要的特定属性。我重用了items
变量来分配递归调用的结果。你不需要这样做,但它可以缩短它,而不必为此目的声明一个变量。
这是一个使用.reduce()
帮助满足linter的版本,但现在我们已经失去了短路: - (。
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))
好的,还有一个。这是最后一个的一个小变化。由于我们讨论的是使用尾递归的纯函数式编程,因此定义将头部与尾部分开的参数很有用。 传播语法和 rest语法使这变得简单。
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))