I have the following function, which I believe could be improved with functional-programming.
function findSelectedInList(list){
for(var i=0;i<=list.length;i++){
var currentItem = list[i];
if(currentItem.selected === "selected"){
return currentItem;
}
var selectedNode = findSelectedInList(currentItem.children)
if(selectedNode){
return selectedNode;
}
}
return void 0;
}
Here are some sample inputs:
var treeList = [ { "roleName": "User",
"roleId": "role1",
"children": [ { "roleName": "subUser1", "roleId": "role11", "children": [], "selected": "selected" }]
}];
var treeList2 = [ { "roleName": "User", "roleId": "role1", "children": [],"selected":"selected"}];
1 Answer 1
Initially, I considered suggesting using Array.filter() but then that wouldn't allow breaking out of the loop once a selected item was found.
One approach is to use Array.some() or Array.find() (and disregard the return value) with a ternary operator. A variable can be initialized as the first line, then the .some() callback returns the result of setting that variable to either the current item if it is selected, otherwise the return value of the recursive call.
function findSelectedInList(list) {
var selected;
list.some(function(currentItem) {
return selected = currentItem.selected === "selected" ? currentItem : findSelectedInList(currentItem.children);
});
return selected;
}
And one could use ecmascript-6 features like arrow functions and the let
keyword), to condense it slightly:
function findSelectedInList(list){
let selected;
list.some((currentItem) => selected = currentItem.selected === "selected" ? currentItem : findSelectedInList(currentItem.children));
return selected;
}
To see this demonstrated, expand the snippet below.
var treeList = [{
"roleName": "User",
"roleId": "role1",
"children": [{
"roleName": "subUser1",
"roleId": "role11",
"children": [],
"selected": "selected"
}]
}];
var treeList2 = [{
"roleName": "User",
"roleId": "role1",
"children": [],
"selected": "selected"
}];
var treeList3 = [{
"roleName": "User",
"roleId": "role1",
"children": []
}];
function findSelectedInList(list) {
var selected;
list.some(function(currentItem) {
return selected = currentItem.selected === "selected" ? currentItem : findSelectedInList(currentItem.children);
});
return selected;
}
console.log('treeList: ', findSelectedInList(treeList));
console.log('treeList2: ', findSelectedInList(treeList2));
console.log('treeList3: ', findSelectedInList(treeList3));
I know it doesn't really cover the find or some methods, but these functional JS exercises are a good thing to go through.
return (currentItem.selected === "selected") || findSelectedInList(currentItem.children)
would have fewer variables and "look" more recursive. \$\endgroup\$selected
set? If not, may any item withselected
set be returned? \$\endgroup\$