Javascript Typescript-在多维对象中查找匹配的键和路径
简言之;如何在多个对象中检索共享键的所有值 更长: 我得到了以下对象,它们存储在一个名为Javascript Typescript-在多维对象中查找匹配的键和路径,javascript,typescript,object,recursion,multidimensional-array,Javascript,Typescript,Object,Recursion,Multidimensional Array,简言之;如何在多个对象中检索共享键的所有值 更长: 我得到了以下对象,它们存储在一个名为collection的数组中: [ names: { "one": "square"; "two": { "three": "circle" "four": { "five": "triangle" } } }
collection
的数组中:
[
names: {
"one": "square";
"two": {
"three": "circle"
"four": {
"five": "triangle"
}
}
}
shapes: {
"one": "[]";
"two": {
"three": "()"
"four": {
"five": "/\"
}
}
}
]
我在Angular(v8.x.x)中创建了一个菜单系统,可以从名称
对象中读取键。
当我点击“circle”菜单项时,我希望获得键值对及其路径,以便在编辑窗口中使用。每个项目都需要这样做。
例:
我曾试图自己创建一个递归函数,但到目前为止还没有得到任何可行的结果。
我还尝试了Scott的惊人示例,尽管angular/typescript不幸地在assocPath()中的ps
定义上抛出了一个错误:
此外,我还参考了以下答案:
1:
2:
第一个在声明前使用的path
是一个块作用域变量,因此有一个错误,我目前正在对方案中的第二个进行故障排除。Update
当我最初写这篇文章时,我显然是在剪切和粘贴其他地方的一些代码,因为我包含了两个根本没有被使用的函数。它们现在被移除了
我还在下面的答案中添加了一个解释,说明如何逐步将其中一个函数从ES5样式转换为现代JS版本。我相信ES6+是一个重大的改进,我喜欢这个函数,因为我写得更好,但是对于那些学习现代JS的人来说,这样的解释可能会有用
更新后的原始答案如下,然后是这些转换步骤
我真的不清楚你在找什么。我的最佳猜测是,您希望接受一个如上所述的对象数组,并返回一个函数,该函数接受一个值,如“circle”
或“()”
,并返回其中一个对象上该值的路径,即['two','three']
。但这一猜测可能远远不够
以下是一个基于几个可重用函数的版本:
//助手
常量路径=(ps=[],obj={})=>
ps.reduce((o,p)=>(o |{})[p],obj)
常量findLeafPaths=(o,path=[[]])=>
o的类型==‘对象’
? Object.entries(o).flatMap(
([k,v])=>findleafpath(v,path).map(p=>[k,…p])
)
:路径
//主要功能
const makeSearcher=(xs)=>{
const structure=xs.reduce(
(a,x)=>findleafpath(x).reduce((a,p)=>({…a[path(p,x)]:p}),a),
{}
)
return(val)=>structure[val]| |[]//其他内容?还是抛出错误?
}
//示范
常量objs=[
{1:“正方形”,2:{3:“圆形”,4:{5:“三角形”}},
{1:[]、2:{3:(())、4:{5:/\\\\'}}
]
const searcher=makeSearcher(objs)
console.log(searcher(“()”)/~>['two','three']
console.log(searcher('circle'))/~>['two','three']
console.log(searcher('triangle'))/~>['two',four','five']
console.log(搜索器('[]')/~>['one']
console.log(searcher('heptagon'))/~>[]
我已经解决了当前的跳闸点
const assocPath = ([p = undefined, ...ps], val, obj) =>
p == undefined
? obj
: assoc (p, ps.length ? assocPath ([ps], val, obj[p] || {}) : val, obj)
功能现在可以按预期工作。如果只给出希望查找的值,则来自searcher()
的结果还可以返回单个路径。e、 g.searcher(“圆圈”)
返回:[“一”、“二”、“三”]
您的尝试在哪里?我已经尝试了许多的搜索结果。。。在…
循环中,尽管大多数会返回未定义的值,可能是因为尝试使用索引,或者变量传递不正确。在这方面我有点不知所措。听起来你需要一个递归函数。你能给出一个输入和输出的例子吗?正确。输入将是一个集合对象/数组,该集合对象/数组依次包含三个(或更多)对象。e、 g.如果输出应该是key2-1
的名称/路径,则函数必须搜索one.key1.key2.key2-1=john
和two.key1.key2.key2-1=alice
。路径和键不会改变,但“目标”键取决于用户在菜单中选择的内容(所述菜单反映对象的键)。我曾尝试创建一个递归函数,但它很难继续超过键1,这可能是因为括号表示法不适合这种情况。(one[key1][key2][key2-1]
)您想要的输出结构是什么?另外,请分享你的一些尝试。即使它是不完整的,它也能帮助其他人理解你想做什么。我对不清楚的描述表示诚挚的歉意,我自己已经读了好几遍,也不能很好地解释它。您的解释是正确的,我也一直在尝试将您的代码融入其中,尽管有些困难。(毕竟,angular+typescript是相当挑剔的)我认为“结构”目前还不错,也不能真正想出一个合适的替代方案。@eymas:添加了一个很长的解释。还删除了我从另一个问题中粘贴的一些函数,这些函数实际上没有被使用。很抱歉。关于这一点的详细解释与我设法提取的内容相匹配,并且保留了相当好的功能!谢谢你的大力支持!就我个人而言,我更喜欢较短的表示法。如果这是您需要支持的内容,那么您应该每次都返回数组,而不是添加检查,无论是没有路径、一条路径还是多条路径。这可以通过将传递给reduce的(a,p)=>({…a[path(p,x)]:p})函数替换为(a,p)=>({…a[path(p,x)]:[…(a[path(p,x)]|[],p]}
或等价地,(a,p)=>({…a[path(p,x)]:(a[path(p,x)]。[]
。这确实更有意义,是的。谢谢你的快速回复!这是我需要支持的东西,同时也需要能够找到空字符串
|----------
|three:
|circle
|----------
|three:
|()
|----------
Argument of type 'any[]' is not assignable to parameter of type '[any, ...any[]]'.
Property '0' is missing in type 'any[]' but required in type '[any, ...any[]]'.
const assocPath = ([p = undefined, ...ps], val, obj) =>
p == undefined
? obj
: assoc (p, ps.length ? assocPath ([ps], val, obj[p] || {}) : val, obj)