Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从JavaScript对象中动态检索任意指定的深度嵌套值?_Javascript_Arrays_Angular_Recursion_Nested - Fatal编程技术网

如何从JavaScript对象中动态检索任意指定的深度嵌套值?

如何从JavaScript对象中动态检索任意指定的深度嵌套值?,javascript,arrays,angular,recursion,nested,Javascript,Arrays,Angular,Recursion,Nested,重新发布为的更正版本。我已经复习过了,但是它没有帮助我处理未知的数组嵌套 编辑:添加了有关Lodash为什么不起作用的信息。这是一个例子。有一个npm库,它可以工作——但是,我不能很好地使用这个包 这适用于Angular应用程序中的列渲染器组件。用户选择要显示的列,并将该列映射到任何列。因此,在下面的示例中,如果用户选择显示“类别”,并将其映射到“兴趣[类别]”,则函数需要在数据中查找对应于该映射的值 样本数据: const response = { id: "1234"

重新发布为的更正版本。我已经复习过了,但是它没有帮助我处理未知的数组嵌套

编辑:添加了有关Lodash
为什么不起作用的信息。这是一个例子。有一个npm库,它可以工作——但是,我不能很好地使用这个包

这适用于Angular应用程序中的列渲染器组件。用户选择要显示的列,并将该列映射到任何列。因此,在下面的示例中,如果用户选择显示“类别”,并将其映射到“兴趣[类别]”,则函数需要在数据中查找对应于该映射的值

样本数据:

const response = {
  id: "1234",
  version: "0.1",
  drinks: ["Scotch"],
  interests: [
    {
      categories: ["baseball", "football"],
      refreshments: {
        drinks: ["beer", "soft drink"]
      }
    },
    {
      categories: ["movies", "books"],
      refreshments: {
        drinks: ["coffee", "tea", "soft drink"]
      }
    }
  ],
  goals: [
    {
      maxCalories: {
        drinks: "350",
        pizza: "700"
      }
    }
  ]
};
对于此数据,可能的映射为:
id
版本
饮料
兴趣[类别]
兴趣[点心][饮料]
目标[最大热量][饮料]
目标[MaxCarries][pizza]

要求: 我需要一个递归函数,该函数将以Angular方式工作,并接受两个参数:一个用于数据对象
响应
,另一个用于选择器映射的字符串,该字符串将返回适用的、可能嵌套的值,并遍历遇到的任何对象和/或数组。映射字符串可以有点符号或括号符号。非常需要可读、自文档化的代码

例如,基于上述数据对象:

  • getValues(“id”,响应)
    应返回
    [“1234”]
  • getValues(“版本”,响应)
    应返回
    [“0.1”]
  • getvalue(“饮料”,响应)
    应返回
    [“Scotch”]
  • getValues(“interests.categories”,response)
    应该返回
    [“棒球”、“足球”、“电影”、“书籍”]
  • getValues(“兴趣[点心][饮料]”,回复)
    应返回
    [“啤酒”、“软饮料”、“咖啡”、“茶”、“软饮料”]
    ,以说明
    兴趣
    数组中可能有多少项
  • getValues(“goals.maxcarries.drinks”,响应)
    应返回
    [“350”]
返回的值最终将被重复数据消除和排序

原始功能:

function getValues(mapping, row) {
  let rtnValue = mapping
    .replace(/\]/g, "")
    .split("[")
    .map(item => item.split("."))  
    .reduce((arr, next) => [...arr, ...next], [])
    .reduce((obj, key) => obj && obj[key], row)
    .sort();

  rtnValue = [...new Set(rtnValue)]; //dedupe the return values

  return rtnValue.join(", ");
}
上面的操作很好,就像Lodash'get:如果您通过,例如:
“兴趣[0][茶点][饮料]
,它工作得很好。但是,映射不知道嵌套数组,只传入
“兴趣[茶点][饮料]“
,这将导致
未定义
。必须考虑任何后续数组项


为什么要重新发明轮子?您所描述的正是Lodash
get
函数的功能。看

如果你真的想要一个“普通”的解决方案,看看他们是如何做到的。请参见更新 在我给出下面的答案后,我吃了一些晚餐。食物似乎让我意识到我是多么可笑。对于前面的问题,我很清楚我是如何看待这个问题的。但是有一种非常简单的方法,类似于我编写
path
函数的方法,只需要少量额外的复杂性来处理数组的映射。这里有一个更干净的方法:

//主函数
const_getValues=([p,…ps])=>(obj)=>
p==未定义
? 数组。isArray(obj)?obj:[obj]
:Array.isArray(obj)
?  对象平面图(o=>_getValues(ps)(o[p]| |[]))
:_getValues(ps)(obj[p]| |[]))
//公共职能
const getValues=(查询,对象)=>
_getValues(query.split(/[\].]+/g.filter(布尔))(obj)
//样本数据
const response={id:“1234”,版本:“0.1”,饮料:[“苏格兰”],兴趣:[{类别:[“棒球”,“足球”],点心:[饮料:[“啤酒”,“软饮料”]},{类别:[“电影”,“书籍”],点心:[饮料:[“咖啡”,“茶”,“软饮料”]}],目标:[{最大卡路里:[饮料:[350],比萨饼:“700”}};
//演示
[
'id',//=>['1234']
'版本',//=>['0.1']
“饮料”、/=>[“苏格兰威士忌”]
“兴趣[类别],//=>[“棒球”、“足球”、“电影”、“书籍”]
“兴趣[点心][饮料],/=>[“啤酒”、“软饮料”、“咖啡”、“茶”、“软饮料”]
'目标.最大卡路里.饮料',/=>['350']
'goals.maxcarries.notFound',//=>
'foo.bar.baz',//=>
“兴趣[类别][饮料],//=>[]
]弗雷奇先生(
name=>console.log(`“${name}”-->${JSON.stringify(getValues(name,response))}`)
)
.as控制台包装{max height:100%!重要;top:0}
使用语法:

const{tokenizePath,resolveValue}=require('path-value');
函数getValues(路径,obj){
const tokens=tokenizePath(path);//以支持完整的ES5语法
返回解析值(obj、令牌);
}
getValues(“id”,响应);//=>1234

看起来你基本上是想实现Lodash的目标。请参阅我在帖子中添加的说明。
getValues(“兴趣[点心][饮料]”,回复)无效。索引元素只能是数字或带引号的字符串。您是正确的,但这是从数据库返回并传递给函数的字符串。因此,在原始问题中,
replace.split.map.reduce
方法的舞蹈将输入字符串转换为更可接受的内容:
[“兴趣”、“点心”、“饮料”]
在下面的答案中,这在一行中处理得更加优雅:
query.split(/[\].]+/g).filter(布尔)
仍然需要将对象扫描迁移到typescript,以便angular可以处理它。。。一旦我到了itLodash get,我可能会在这里发布一些信息,比如:
\uuu.get(响应,“兴趣[0].categories”,“默认”)但是,将要传递的是:
兴趣.类别
(不带ar