首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据支持值搜索和获取节点?

如何根据支持值搜索和获取节点?
EN

Stack Overflow用户
提问于 2021-01-27 07:41:25
回答 1查看 71关注 0票数 0

大家好,我想根据对象中的支柱值提取一个节点,下面是我想要的

备注:

  1. uniqueId -->是我想要的钥匙。
  2. -是所有嵌套对象的固定键。
  3. “‘item1 1”,...etc -用于搜索对象内部的支柱数组,如下所述

我的目标是:

代码语言:javascript
复制
const obj = {
  home: {
    label: 'home',
    alt: 'home',
    uniqueId: 'home', 
  },
  tasks: {
    label: 'tasks',
    alt: 'tasks',
    uniqueId: 'tasks',
  },
  cms: {
    label: 'cms',
    alt: 'cms',
    uniqueId: 'cms',
    items: {
      news: {
        label:'news',
        alt: 'cms-news',
        uniqueId: 'news',
      },
      announcements: {
        label: 'cmsAnnouncementsLabel',
        alt: 'cms-announcements',
        uniqueId: 'announcements',
      },
    }
  },
  supervision: {
    label: 'supervision',
    alt: 'supervision',
    uniqueId: 'supervision',
    items: {
      violations: {
        label: 'violationsManegment',
        alt: 'supervisors',
        uniqueId: 'violations',
        items: {
          violationTemplates: {
            label: 'violationTemplates',
            alt: 'violations',
            uniqueId: 'violationTemplates',
          },
          paradigms: {
            label: 'paradimsManegment',
            alt: 'paradims',
            uniqueId: 'paradigms',
          },
        }
      }
    }
  }
}

预期结果:

  1. 案例1:如果我想搜索'home',结果将是

代码语言:javascript
复制
const result = {
  home: {
    label: 'home',
    alt: 'home',
    uniqueId: 'home', 
  }
}

  1. 案例2如果要搜索嵌套对象'announcements',结果应该是

代码语言:javascript
复制
const result = {
  cms: {
    label: 'cms',
    alt: 'cms',
    uniqueId: 'cms',
    items: {
      announcements: {
        label: 'cmsAnnouncementsLabel',
        alt: 'cms-announcements',
        uniqueId: 'announcements',
      },
    }
  },
}

注意,新闻被忽略了,因为它不在搜索数组

  1. 案例3如果我想搜索‘范例’,结果将是

代码语言:javascript
复制
const result = {
  supervision: {
    label: 'supervision',
    alt: 'supervision',
    uniqueId: 'supervision',
    items: {
      violations: {
        label: 'violationsManegment',
        alt: 'supervisors',
        uniqueId: 'violations',
        items: {
          paradigms: {
            label: 'paradimsManegment',
            alt: 'paradims',
            uniqueId: 'paradigms',
          },
        }
      }
    }
  }
}

违规模板忽略

4.最后一个例子--如果我想搜索的“violationTemplates”,“home”,“

代码语言:javascript
复制
const result = {
  home: {
    label: 'home',
    alt: 'home',
    uniqueId: 'home', 
  },
  tasks: {
    label: 'tasks',
    alt: 'tasks',
    uniqueId: 'tasks',
  },
  supervision: {
    label: 'supervision',
    alt: 'supervision',
    uniqueId: 'supervision',
    items: {
      violations: {
        label: 'violationsManegment',
        alt: 'supervisors',
        uniqueId: 'violations',
        items: {
          violationTemplates: {
            label: 'violationTemplates',
            alt: 'violations',
            uniqueId: 'violationTemplates',
          },
          paradigms: {
            label: 'paradimsManegment',
            alt: 'paradims',
            uniqueId: 'paradigms',
          },
        }
      }
    }
  }
}

**我使用了deepDash **

我怎么能这么做?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-31 17:26:27

一种可能的实施

我敢说,这个问题可能比开始时更复杂。我尝试使用Lodash创建您给我们的规范的实现,并将其移植到兰布达 _.has_.isObject函数中。得到的代码没有被优化,而且很长,但我希望它可以为您提供一个起点,如果您需要更好的算法,可以对其进行优化。

我能在浏览器中快速尝试这个函数吗?

当然了!实际上,我做了一个Codepen,您可以在其中尝试算法,只需记住打开浏览器控制台就可以看到测试结果!以下是链接:

何塞/pen/ZEBYPbR

如何使用它

代码语言:javascript
复制
//the function signature
result = findDeep(object, query, options);

其中:

  • 对象是要查看内部的对象
  • 查询可以是:
代码语言:javascript
复制
- a string, in which case will treated as the key to search
- an array, in which case each of the elements will be treated as a key to search
  • options是一个可选对象,可以包含以下一个或两个键: {merge: "yes", keeptree: "yes"}
代码语言:javascript
复制
- `merge: "yes"` tells findDeep to do a mergeDeepLeft on the resulting array, such that: a) without it you get back an array with the search results for each of the keys you searched for b) you get one merged object.
- `keeptree: "yes"` tells findDeep to return the whole tree, and not just the object that was attached to the key or keys that we were looking for.
  • 对于用例,应该始终使用两个选项调用findDeep。像这样: result = findDeep(obj, ["key1", "key2"], {merge: "yes", keeptree: "yes"}
  • 结果可以是以下内容之一:
代码语言:javascript
复制
- the object the searched key pointed to (one key, no options)
- an array with a list of objects the searched keys pointed to (multiple keys, no options)
- an object containing all the merged results from all keys (multiple keys, `options = {merge: yes"}`
- by specifying `options = {keeptree: "yes"}` you will also get the keys in the hierarchy of the searched key.

使用实例

我可以看到,我的解释可能是相当人为的,这就是为什么我准备了一系列的例子,希望能够澄清如何使用这个函数。首先,我向您介绍测试数据集,这是您在问题中给我们的:

测试数据集

代码语言:javascript
复制
/* Test dataset */
const dataset = {
  home: {
    label: 'home',
    alt: 'home',
    uniqueId: 'home', 
  },
  tasks: {
    label: 'tasks',
    alt: 'tasks',
    uniqueId: 'tasks',
  },
  cms: {
    label: 'cms',
    alt: 'cms',
    uniqueId: 'cms',
    items: {
      news: {
        label:'news',
        alt: 'cms-news',
        uniqueId: 'news',
      },
      announcements: {
        label: 'cmsAnnouncementsLabel',
        alt: 'cms-announcements',
        uniqueId: 'announcements',
      },
    }
  },
  supervision: {
    label: 'supervision',
    alt: 'supervision',
    uniqueId: 'supervision',
    items: {
      violations: {
        label: 'violationsManegment',
        alt: 'supervisors',
        uniqueId: 'violations',
        items: {
          violationTemplates: {
            label: 'violationTemplates',
            alt: 'violations',
            uniqueId: 'violationTemplates',
          },
          paradigms: {
            label: 'paradimsManegment',
            alt: 'paradims',
            uniqueId: 'paradigms',
          },
        }
      }
    }
  }
};

示例

案例1

代码语言:javascript
复制
//CASE 1
result = findDeep(dataset, "home", {keeptree: "yes"});
result = {
            "label": "tasks",
            "alt": "tasks",
            "uniqueId": "tasks",
            "items": {
                "violations": {
                    "label": "violationsManegment",
                    "alt": "supervisors",
                    "uniqueId": "violations",
                    "items": {
                        "violationTemplates": {
                            "label": "violationTemplates",
                            "alt": "violations",
                            "uniqueId": "violationTemplates"
                        },
                        "paradigms": {
                            "label": "paradimsManegment",
                            "alt": "paradims",
                            "uniqueId": "paradigms"
                        }
                    }
                },
                "announcements": {
                    "label": "cmsAnnouncementsLabel",
                    "alt": "cms-announcements",
                    "uniqueId": "announcements"
                }
            }
        }

案例2

代码语言:javascript
复制
//CASE 2
result = findDeep(dataset, "announcements", {keeptree: "yes"});
result = {
    "cms": {
        "label": "cms",
        "alt": "cms",
        "uniqueId": "cms",
        "items": {
            "announcements": {
                "label": "cmsAnnouncementsLabel",
                "alt": "cms-announcements",
                "uniqueId": "announcements"
            }
        }
    }
}

案例3

代码语言:javascript
复制
//CASE 3
result = findDeep(dataset, "paradigms", {keeptree: "yes"});
result = {
    "supervision": {
        "label": "supervision",
        "alt": "supervision",
        "uniqueId": "supervision",
        "items": {
            "violations": {
                "label": "violationsManegment",
                "alt": "supervisors",
                "uniqueId": "violations",
                "items": {
                    "paradigms": {
                        "label": "paradimsManegment",
                        "alt": "paradims",
                        "uniqueId": "paradigms"
                    }
                }
            }
        }
    }
}

案例4

代码语言:javascript
复制
//CASE 4
result = findDeep(dataset, ['violationTemplates', 'home', 'paradigms'], {merge: "yes", keeptree: "yes"});
result = {
    "supervision": {
        "label": "supervision",
        "alt": "supervision",
        "uniqueId": "supervision",
        "items": {
            "violations": {
                "label": "violationsManegment",
                "alt": "supervisors",
                "uniqueId": "violations",
                "items": {
                    "paradigms": {
                        "label": "paradimsManegment",
                        "alt": "paradims",
                        "uniqueId": "paradigms"
                    },
                    "violationTemplates": {
                        "label": "violationTemplates",
                        "alt": "violations",
                        "uniqueId": "violationTemplates"
                    }
                }
            }
        }
    },
    "home": {
        "label": "home",
        "alt": "home",
        "uniqueId": "home"
    }
}

案例4b

代码语言:javascript
复制
//CASE 4b
result = findDeep(dataset, ['home', 'paradigms'], {merge: "yes", keeptree: "yes"});
result = {
    "supervision": {
        "label": "supervision",
        "alt": "supervision",
        "uniqueId": "supervision",
        "items": {
            "violations": {
                "label": "violationsManegment",
                "alt": "supervisors",
                "uniqueId": "violations",
                "items": {
                    "paradigms": {
                        "label": "paradimsManegment",
                        "alt": "paradims",
                        "uniqueId": "paradigms"
                    }
                }
            }
        }
    },
    "home": {
        "label": "home",
        "alt": "home",
        "uniqueId": "home"
    }
}

下面的附加部分:功能所做的不需要的事情。

额外1

代码语言:javascript
复制
//EXTRA 1
result = findDeep(dataset, "violationTemplates");
result = {
    "label": "supervision",
    "alt": "supervision",
    "uniqueId": "supervision",
    "items": {
        "violations": {
            "label": "violationsManegment",
            "alt": "supervisors",
            "uniqueId": "violations",
            "items": {
                "violationTemplates": {
                    "label": "violationTemplates",
                    "alt": "violations",
                    "uniqueId": "violationTemplates"
                }
            }
        }
    }
}

额外2

代码语言:javascript
复制
//EXTRA 2
result = findDeep(dataset, ["supervision", "violationTemplates", "announcements", "tasks"]);
result = [
    {
        "label": "supervision",
        "alt": "supervision",
        "uniqueId": "supervision",
        "items": {
            "violations": {
                "label": "violationsManegment",
                "alt": "supervisors",
                "uniqueId": "violations",
                "items": {
                    "violationTemplates": {
                        "label": "violationTemplates",
                        "alt": "violations",
                        "uniqueId": "violationTemplates"
                    },
                    "paradigms": {
                        "label": "paradimsManegment",
                        "alt": "paradims",
                        "uniqueId": "paradigms"
                    }
                }
            }
        }
    },
    {
        "label": "supervision",
        "alt": "supervision",
        "uniqueId": "supervision",
        "items": {
            "violations": {
                "label": "violationsManegment",
                "alt": "supervisors",
                "uniqueId": "violations",
                "items": {
                    "violationTemplates": {
                        "label": "violationTemplates",
                        "alt": "violations",
                        "uniqueId": "violationTemplates"
                    }
                }
            }
        }
    },
    {
        "label": "cms",
        "alt": "cms",
        "uniqueId": "cms",
        "items": {
            "announcements": {
                "label": "cmsAnnouncementsLabel",
                "alt": "cms-announcements",
                "uniqueId": "announcements"
            }
        }
    },
    {
        "label": "tasks",
        "alt": "tasks",
        "uniqueId": "tasks"
    }
]

额外3

代码语言:javascript
复制
//EXTRA 3
result = findDeep(dataset, ["supervision", "violationTemplates", "announcements", "tasks"], {merge: "yes"});
result = {
    "label": "tasks",
    "alt": "tasks",
    "uniqueId": "tasks",
    "items": {
        "violations": {
            "label": "violationsManegment",
            "alt": "supervisors",
            "uniqueId": "violations",
            "items": {
                "violationTemplates": {
                    "label": "violationTemplates",
                    "alt": "violations",
                    "uniqueId": "violationTemplates"
                },
                "paradigms": {
                    "label": "paradimsManegment",
                    "alt": "paradims",
                    "uniqueId": "paradigms"
                }
            }
        },
        "announcements": {
            "label": "cmsAnnouncementsLabel",
            "alt": "cms-announcements",
            "uniqueId": "announcements"
        }
    }
}

源代码

代码语言:javascript
复制
const findDeep = ( () => {
  /* Libraries */

  /* This code was forked from Rambda by Jacopo Tedeschi. Dependencies were adjusted so that it depends on Lodash instead.
     It wouldn't be hard to even make it completely library independent  */
  const mergeWithKey = function mergeWithKey(fn, l, r) {
    var result = {};
    var k;

    for (k in l) {
      if (_.has(l, k)) {
        if(_.has(r, k))
        {
            result[k] = fn(k, l[k], r[k]);
        } else {
            result[k] = l[k];
        }
      }
    }

    for (k in r) {
      if (_.has(r, k) && !(_.has(result, k))) {
        result[k] = r[k];
      }
    }

    return result;
  };

  const mergeDeepWithKey = function mergeDeepWithKey(fn, lObj, rObj) {
    return mergeWithKey(function(k, lVal, rVal) {
      if (_.isObject(lVal) && _.isObject(rVal)) {
        return mergeDeepWithKey(fn, lVal, rVal);
      } else {
        return fn(k, lVal, rVal);
      }
    }, lObj, rObj);
  };

  const mergeDeepLeft = function mergeDeepLeft(lObj, rObj) {
    return mergeDeepWithKey(function(k, lVal, rVal) {
      return lVal;
    }, lObj, rObj);
  };
  
  /* Code below here was written by Jacopo Tedeschi */
  
  function _deleteSibilings(object, searchKey) {
    return _.has(object, searchKey)
           ? {[searchKey] : object[searchKey]}
           : _.reduce(object, (acc, value, key) => {
                      acc[key] = _.isObject(value)
                                 ? _deleteSibilings(value, searchKey)
                                 : value;
                      return acc;
              }, {});
   };
  
  function _findDeepHelper(collection, key, options)
  {  
    if(_.has(collection, key))
    {
      //here we make sure we also return the key
      return _.get(options, "keeptree") == "yes"
              ? key
              : collection[key];
    } else 
    {
      const resultKey = _.findKey(collection, 
                                  value =>  _.isObjectLike(value)
                                            && _findDeepHelper(value, key, options));
      
      return _.get(options, "keeptree") == "yes"
             ? resultKey
             : _.get(collection, resultKey);
    }
  }
  
  function _findDeep(collection, key, options)
  {
    let result = _findDeepHelper(collection, key, options);
    
    if(_.get(options, "keeptree") == "yes")
    {
      result = _.pick(collection, result);
    }
    
    return _deleteSibilings(result, key);
  }
  
  function _findMultipleDeep(collection, keys, options)
  {
    return _.isArray(keys)
           ? _.map(keys, key => _findDeep(collection, key, options)) 
           : _findDeep(collection, keys, options);
  }
  
  function _mergeQueries(queries)
  {
    if(_.isArray(queries))
    {
      return queries.length > 1
             ? _.reduce(queries, mergeDeepLeft)
             : _.get(queries, 0);
    } else
    {
      return queries;
    }
  }
  
  return (collection, keys, options) =>
  {
      const result = _findMultipleDeep(collection, keys, options);
      return  _.get(options, "merge") == "yes"
              ? _mergeQueries(result)
              : result;
  };
})();

算法说明

只搜索一个键

这就是我在算法中创建所需的result对象的顺序:

  1. 查看IIE内部(立即调用表达式),我使用它来分隔我的作用域并避免全局范围污染。
  2. 首先要看的是_findDeep函数。算法的第一部分在那里处理。
  3. 它调用_findDeepHelper,它执行以下操作:
    1. 搜索是使用递归算法在对象中找到的密钥。
    2. 找到钥匙后,它会穿过树回来。
    3. 上升时,它返回当前节点的键名。
    4. 因此,我们返回对象根目录中最上面节点的键,其中包含我们要查找的键。

  4. 然后,使用Lodash _.pick创建一个新对象,只选择包含我们要查找的键的根键。
  5. 最后,使用_deleteSibilings删除我们要寻找的密钥的所有兄弟姐妹。
  6. 我们现在有了结果对象!

搜索多键

那么,你如何搜索多个密钥呢?

  1. 为了简化,我从Rambda库中分叉了mergeDeepLeft,并更改了一些函数,使其依赖于Lodash。
  2. 我分别进行每个搜索,然后使用mergeDeepLeft将查询合并在一起。
  3. 如果存在冲突键,则搜索键数组左侧的键数据将丢失,仅保留右侧键所产生的键。

为什么也有我没有请求的功能?

由于我是这样做的,我只花了一点额外的时间,并使生成的算法(我称之为findDeep )更加灵活和方便地在不同的用例中使用。这只产生了一点点额外的代码,但我希望这样能更好地为您服务。

感谢您的阅读!

我很乐意作进一步的解释,也许你需要它。另外,我想补充的是,可以编写一些聪明的实用程序函数作为lowdb/lodash,以便使我们有一个更短的语法和仍然正确的链。不过,这可能比你想要的要多。

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

https://stackoverflow.com/questions/65914764

复制
相关文章

相似问题

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