首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于根据对象的UID定位对象的递归JavaScript函数

用于根据对象的UID定位对象的递归JavaScript函数
EN

Stack Overflow用户
提问于 2018-06-14 05:02:45
回答 3查看 57关注 0票数 0

我在返回在这个层次树中找到的元素时遇到了问题。例如,如果我选择的项目是:

{
 "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;
		}
	}

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-14 05:12:48

使用递归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))

票数 1
EN

Stack Overflow用户

发布于 2018-06-14 05:17:50

您可以使用显式函数来搜索所需的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; }

票数 1
EN

Stack Overflow用户

发布于 2018-06-14 06:16:11

要做到这一点,一种方法是编写一个相当通用的树查找函数版本,然后针对您的特定问题对其进行配置。在这里,我们选择通过匹配提供的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
)

泛型函数并不总是正确的答案。但它们可以帮助我们将那些从我们正在编写的更基本的算法中改变的东西分离出来。我认为在这种情况下,它有助于使事情更容易维护。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50846231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档