Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/459.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_Object_Recursion_Tree - Fatal编程技术网

Javascript 在相互引用的对象数组上迭代,并将这些对象从一个字符串解析到另一个对象

Javascript 在相互引用的对象数组上迭代,并将这些对象从一个字符串解析到另一个对象,javascript,arrays,object,recursion,tree,Javascript,Arrays,Object,Recursion,Tree,我正在创建一个预设系统,其中预设可以“包括”其他预设 预设A包括预设B和C,预设B包括D和E 它们都有这样的结构: -身份证 -名称(字符串,在include中用作引用) -内容(字符串数组) -include(名称数组,对应于名称属性) 内容就是包含的内容 在过去的两天里,我试着想出一个解决方案,试着围绕递归来思考。我在这里查看了与递归相关的文章,但没有任何内容真正适合我的场景 function getIncludes (original) { let output = [];

我正在创建一个预设系统,其中预设可以“包括”其他预设

预设A包括预设B和C,预设B包括D和E

它们都有这样的结构: -身份证 -名称(字符串,在include中用作引用) -内容(字符串数组) -include(名称数组,对应于名称属性)

内容就是包含的内容

在过去的两天里,我试着想出一个解决方案,试着围绕递归来思考。我在这里查看了与递归相关的文章,但没有任何内容真正适合我的场景

function getIncludes (original) {
    let output = [];

    function recursion (package) {
        if (package.content) output.push(package.content.join(' '));
        if (package.include) {
            return package.include.forEach(str => {
                let c = presets.find(obj => obj.name === str);
                if (c.content) output.push(c.content.join(' '));
                    recursion(c)
            });
        }
    }

    recursion(original);
    return output.join(' ');
}
示例预设obj

[
  {
    "id": 0,
    "name": "videoFormats",
    "content": ["(avi|mkv|mov|mp4|mpg|wmv)"],
    "hidden": true,
    "include": ["imageFormats"]
  },
  {
    "name": "audioFormats",
    "id": 1,
    "content": ["(ac3|flac|m4a|mp3|ogg|wav|wma)"],
    "hidden": true,
    "include": ["imageFormats"]
  },
  {
    "id": 2,
    "name": "imageFormats",
    "content": ["(bmp|gif|jpg|jpeg|png|psd|tif|tiff)"],
    "hidden": true
  },
  {
    "id": 3,
    "name": "media",
    "title": "Media",
    "include": ["videoFormats", "audioFormats"],
    "hidden": false
  }
]
我需要一个功能,给我一个预设列表,选择的预设取决于

这样的函数可以工作

getIncludes("media") returning ["videoFormats", "audioFormats", "imageFormats"]

您可以按名称获取访问的所有预设对象,然后获取包含值。要获取唯一项,可以获取一个
,并省略两个项

函数getIncludes(原始){ 如果(!presets[原始])返回[]; return[].concat(预设值[原始值])。include | |[])。reduce( (r,name)=>[…r,…getIncludes(name)], [原件] ); } var数据={id:0,名称:“视频格式”,内容:VAVAR数据={{{id:0,名称:“视频格式”,名称:“视频格式,名称:“视频格式”,名称:1,名称:“名称:“视频格式”,名称:名为:“视频格式”,内容:数据:7,隐藏:真实,包括:Va0.7,身份:隐藏:真实,包括:“图像格式”,身份:包括:包括:“图像格式,{id:1,名称:1,名称:“音名:“视频格式”,id:1,名称:1,名称:“音频格式”,内容,内容:名称,内容:1,内容:1,内容:1,内容:1,内容:1,内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:内容:[“(“(”(”(”(”(”(ac3(ac3(AC3124312431243124312431243|美国联邦政府军军军军方方方方方方是的},{id:3,名称:“媒体”,标题:“媒体”,包括:[“视频格式”、“音频格式”],隐藏:false}], 预设=数据.reduce((r,o)=>(r[o.name]=o,r),{}); log(getIncludes('videoFormats'); log(getIncludes('audioFormats'); log(getIncludes('imageFormats'); console.log(getIncludes('media');
.as控制台包装{最大高度:100%!重要;顶部:0;}
首先,我们需要考虑某种类型的
T
,它允许通过
name
高效地查找特定预设。数组不提供此类功能,因此我们将从数组转换为所需类型
T
。在这种情况下,我们将使用
Map
-

// type preset =
//   { id: number
//   , name: string
//   , content: string array
//   , hidden: bool
//   , include: string array
//   }

// type t =
//   (string, preset) map
上面我们看到
t
是一个
映射
,它有
字符串
键,每个键指向一个
预设值。现在我们可以从数组
写入

// fromArray : preset array -> t
const fromArray = (a = []) =>
  a.reduce((r,x) => r.set(x.name, x), new Map)
现在我们可以很容易地通过
name
找到一个预设,我们编写了一个通用的遍历过程。这允许我们将1)树的遍历与2)我们希望对每个树元素执行的预期操作分开-

// traverse : (t, string) -> preset generator
const traverse = function* (t = new Map, name = "") {
  if (!t.has(name)) return
  yield* traverse1(t, t.get(name))
}

// traverse1 : (t, preset) -> preset generator
const traverse1 = function* (t = new Map, preset = {}) {
  yield preset
  for (const i of preset.include || [])
    yield* traverse(t, i)
}
现在,我们的
getIncludes
函数可以是一个简单的程序。它不再需要关注树遍历,而是可以专注于将
预设的
元素的线性序列转换为所需的字符串集-

const getIncludes = (t = new Map, name = "") =>
{ const r = new Set
  for (const p of traverse(t, name))
    if (r.has(p.name) || p.name === name)
      continue
    else
      r.add(p.name)
  return Array.from(r)
}
正如您所看到的,从依赖于我们的树的每个函数中删除遍历逻辑是一个巨大的帮助-

const tree =
  fromArray(presets)

getIncludes(tree, "media")
// [ "videoFormats", "imageFormats", "audioFormats" ]

getIncludes(tree, "audioFormats")
// [ "imageFormats" ]

getIncludes(tree, "imageFormats")
// []
展开下面的代码段,在您自己的浏览器中验证结果-

const预设=
[{id:0
,名称:“视频格式”
,内容:[“(avi | mkv | mov | mp4 | mpg | wmv)]
,隐藏:正确
,包括:[“图像格式”]
}
,{id:1
,名称:“音频格式”
,内容:[“(ac3 | flac | m4a | mp3 | ogg | wav | wma)]
,隐藏:正确
,包括:[“图像格式”]
}
,{id:2
,名称:“图像格式”
,内容:[“(bmp | gif | jpg | jpeg | png | psd | tif | tiff)”]
,隐藏:正确
}
,{id:3
,名称:“媒体”
,标题:“媒体”
,包括:[“视频格式”、“音频格式”]
,隐藏:假
}
]
常量fromArray=(a=[])=>
a、 reduce((r,x)=>r.set(x.name,x),新地图)
常量遍历=函数*(t=新映射,名称=“”){
如果(!t.has(name))返回
收益率*traverse1(t,t.get(名称))
}
const traverse1=函数*(t=新映射,预设={}){
产量预设
对于(预置的常数i.include | |[]))
收益率*横向(t,i)
}
const getIncludes=(t=新映射,name=”“)=>
{const r=新集合
for(导线常数p(t,名称))
if(r.has(p.name)| | p.name===name)
持续
其他的
r、 添加(p.name)
返回数组.from(r)
}
常数树=
fromArray(预设)
log(getIncludes(树,“媒体”))
//[“视频格式”、“图像格式”、“音频格式”]
log(getIncludes(树,“音频格式”))
//[“图像格式”]
log(getIncludes(树,“imageFormats”))

//[]
请添加想要的结果。预设的“A”是什么?当用户选择预设A时,所包含预设的内容字段应合并为预设内容字段。您是否可以添加实际的预期输出?如果您在输入之外还指定了输出的确切外观,则更容易确定。此外,
include
不是每个y的字符串数组我们的示例,它要么是字符串,要么是字符串数组,它总是应该是一个数组(如果它是一致的,这会稍微简化事情)。include总是一个字符串数组,在准备示例时忘记了括号。