代码之家  ›  专栏  ›  技术社区  ›  bob.mazzo

递归的javascript函数,通过其uid定位对象

  •  0
  • bob.mazzo  · 技术社区  · 7 年前

    例如,如果我选择的项目是:

    {
     "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;
    		}
    	}
    3 回复  |  直到 7 年前
        1
  •  1
  •   CertainPerformance    7 年前

    使用递归更容易 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))
        2
  •  1
  •   Nina Scholz    7 年前

    您可以使用一个显式函数来搜索所需的 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; }
        3
  •  1
  •   Scott Sauyet    7 年前

    实现这一点的一种方法是编写一个相当通用的树查找函数版本,然后针对特定的问题对其进行配置。在这里,我们选择通过匹配提供的uid进行测试,我们通过查看 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 直接传递,但要传递的元素 属性,我们可以写

    const matchElem = (elem) => (item) => elem.UID === item.UID
    

    const findUid2 = (elem, tree) => searchTreeDF(subs, matchElem(elem), convert, tree)
    // ...
    findUid2({UID: 49}, tree)
    

    或者如果我们不想转换结果,并保留 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
    )