我在返回在此分层树中找到的元素时遇到问题。 例如,如果我选择的项目是:
{
"UID": 49,
"GUID": "",
"LocationName": "Doctor Smith's Office",
"LocationType": {
"UID": 2,
"LocationTypeName": "Practice",
"Description": "other location"
}
}
我将UID
与下面的对象数组进行匹配。
{
UID: 2,
GUID: "",
LocationName: "USA",
ParentLocation: null,
subs: [{
UID: 42,
GUID: "",
LocationName: "New Jersey",
Description: "",
subs: [{
UID: 3,
GUID: "",
LocationName: "Essex County",
ParentLocation: null,
"subs":[
UID: 4,
LocationName: "Newark",
ParentLocation: 3,
"subs": [
{
"UID": 49,
"GUID": "",
"LocationName": "Doctor Smith's Office",
"LocationType": {
"UID": 2,
"LocationTypeName": "Practice",
"Description": "other location"
},
"subs": [
{
"HostID": 38,
"HostName": "Ocean Host",
}
]
}
]
]
}
]
}]
};
let foundItem = this.findInTreeView(this.treeviewData[0], node.selectedNode);
// find selected node in treeview nav
// param: data - the treeview dataset
// param: selected - the selected node to be searched for in param 'data'
findInTreeView(data: any, selected: any ) {
let found;
if (this.foundInTree(data, selected)) {
return data;
}
let elem;
let ary = data.subs;
for (var i=0; i < ary.length; i++) {
elem = ary[i];
if (this.foundInTree(elem, selected)) {
// *** PROBLEM: If func has return true, I want to return the 'elem' object.
return elem;
}
}
for (var i=0; i < ary.length; i++) {
elem = ary[i];
if (elem.subs !== undefined) {
// recurse subs array
let found = this.findInTreeView(elem, selected);
if (found) {
return elem;
}
}
}
//return elem;
}
foundInTree(treeItem, node) {
if (treeItem.UID === node.UID) {
return true;
}
else {
return false;
}
}
使用递归reduce
函数要容易得多,如下所示:
const input={UID:2,GUID:"",LocationName:"USA",ParentLocation:null,subs:[{UID:42,GUID:"",LocationName:"New Jersey",Description:"",subs:[{UID:3,GUID:"",LocationName:"Essex County",ParentLocation:null,"subs":[{UID:4,LocationName:"Newark",ParentLocation:3,"subs":[{"UID":49,"GUID":"","LocationName":"Doctor Smith's Office","LocationType":{"UID":2,"LocationTypeName":"Practice","Description":"other location"},"subs":[{"HostID":38,"HostName":"Ocean Host",}]}]}]}]}]};
const findUIDObj = (uid, parent) => {
const { UID, subs } = parent;
if (UID === uid) {
const { subs, ...rest } = parent;
return rest;
}
if (subs) return subs.reduce((found, child) => found || findUIDObj(uid, child), null);
};
console.log(findUIDObj(49, input))
您可以使用显式函数来搜索所需的UID
。
function find(array, UID) {
var object;
array.some(o => {
if (o.UID === UID) {
return object = o;
}
return object = find(o.subs, UID);
});
return object;
}
var object = { UID: 2, GUID: "", LocationName: "USA", ParentLocation: null, subs: [{ UID: 42, GUID: "", LocationName: "New Jersey", Description: "", subs: [{ UID: 3, GUID: "", LocationName: "Essex County", ParentLocation: null, subs: [{ UID: 4, LocationName: "Newark", ParentLocation: 3, subs: [{ UID: 49, GUID: "", LocationName: "Doctor Smith's Office", LocationType: { UID: 2, LocationTypeName: "Practice", Description: "other location" }, subs: [{ HostID: 38, HostName: "Ocean Host", }] }] }] }] }] };
console.log(find([object], 49));
.as-console-wrapper { max-height: 100% !important; top: 0; }
一种方法是编写树查找函数的相当通用的版本,然后针对您的特定问题对其进行配置。 在这里,我们选择通过在提供的 UID 上进行匹配来进行测试,我们通过查看subs
属性下降到子属性,并通过去除subs
属性来转换结果:
const searchTreeDF = (kids, test, convert, node) => test(node) // depth-first search
? convert(node)
: (kids(node) || []).reduce(
(found, child) => found || searchTreeDF(kids, test, convert, child),
false
)
const subs = node => node.subs
const matchId = (uid) => (item) => item.UID === uid
const convert = ({subs, ...rest}) => ({...rest})
const findUid = (uid, tree) => searchTreeDF(subs, matchId(uid), convert, tree)
// ...
const tree = {"GUID": "", "LocationName": "USA", "ParentLocation": null, "UID": 2, "subs": [{"Description": "", "GUID": "", "LocationName": "New Jersey", "UID": 42, "subs": [{"GUID": "", "LocationName": "Essex County", "ParentLocation": null, "UID": 3, "subs": [{"LocationName": "Newark", "ParentLocation": 3, "UID": 4, "subs": [{"GUID": "", "LocationName": "Doctor Smith's Office", "LocationType": {"Description": "other location", "LocationTypeName": "Practice", "UID": 2}, "UID": 49, "subs": [{"HostID": 38, "HostName": "Ocean Host"}]}]}]}]}]}
console.log(findUid(49, tree))
但是,如果我们不想直接传入UID
,而是想传入具有自己的UID
属性的元素,我们可以编写
const matchElem = (elem) => (item) => elem.UID === item.UID
然后执行此操作:
const findUid2 = (elem, tree) => searchTreeDF(subs, matchElem(elem), convert, tree)
// ...
findUid2({UID: 49}, tree)
或者,如果我们想不转换结果,并保留subs
属性,我们可以只为convert
提供一个恒等函数:
const findUid = (uid, tree) => searchTreeDF(subs, matchId(uid), x => x, tree)
或者我们可以随心所欲地混合搭配。 另请注意,配置不必使用命名函数。 我们可以很容易地写
const findUid = (uid, tree) => searchTreeDF(
node => node.subs || [],
(item) => item.UID === uid,
({subs, ...rest}) => ({...rest}),
tree
)
泛型函数并不总是正确的答案。 但它们可以帮助将那些从我们正在编写的更基本的算法中改变的东西区分开来。 我认为在这种情况下,它有助于使事情更易于维护。