大家好,我想根据对象中的支柱值提取一个节点,下面是我想要的
备注:
我的目标是:
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',
},
}
}
}
}
}
预期结果:
const result = {
home: {
label: 'home',
alt: 'home',
uniqueId: 'home',
}
}
const result = {
cms: {
label: 'cms',
alt: 'cms',
uniqueId: 'cms',
items: {
announcements: {
label: 'cmsAnnouncementsLabel',
alt: 'cms-announcements',
uniqueId: 'announcements',
},
}
},
}
注意,新闻被忽略了,因为它不在搜索数组中
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”,“”
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 **
我怎么能这么做?
发布于 2021-01-31 17:26:27
一种可能的实施
我敢说,这个问题可能比开始时更复杂。我尝试使用Lodash创建您给我们的规范的实现,并将其移植到兰布达 _.has和_.isObject函数中。得到的代码没有被优化,而且很长,但我希望它可以为您提供一个起点,如果您需要更好的算法,可以对其进行优化。
我能在浏览器中快速尝试这个函数吗?
当然了!实际上,我做了一个Codepen,您可以在其中尝试算法,只需记住打开浏览器控制台就可以看到测试结果!以下是链接:
如何使用它
//the function signature
result = findDeep(object, query, options);其中:
- 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{merge: "yes", keeptree: "yes"}- `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.result = findDeep(obj, ["key1", "key2"], {merge: "yes", keeptree: "yes"}- 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.使用实例
我可以看到,我的解释可能是相当人为的,这就是为什么我准备了一系列的例子,希望能够澄清如何使用这个函数。首先,我向您介绍测试数据集,这是您在问题中给我们的:
测试数据集
/* 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
//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
//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
//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
//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
//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
//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
//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
//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"
}
}
}源代码
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对象的顺序:
_findDeep函数。算法的第一部分在那里处理。_findDeepHelper,它执行以下操作:_.pick创建一个新对象,只选择包含我们要查找的键的根键。_deleteSibilings删除我们要寻找的密钥的所有兄弟姐妹。搜索多键
那么,你如何搜索多个密钥呢?
mergeDeepLeft,并更改了一些函数,使其依赖于Lodash。mergeDeepLeft将查询合并在一起。为什么也有我没有请求的功能?
由于我是这样做的,我只花了一点额外的时间,并使生成的算法(我称之为findDeep )更加灵活和方便地在不同的用例中使用。这只产生了一点点额外的代码,但我希望这样能更好地为您服务。
感谢您的阅读!
我很乐意作进一步的解释,也许你需要它。另外,我想补充的是,可以编写一些聪明的实用程序函数作为lowdb/lodash,以便使我们有一个更短的语法和仍然正确的链。不过,这可能比你想要的要多。
https://stackoverflow.com/questions/65914764
复制相似问题