递归地迭代嵌套对象以更改所有出现的键值JS

如何解决递归地迭代嵌套对象以更改所有出现的键值JS

我有一个令人困惑的数据对象,它里面包含对象和数组内的对象,因为它作为一个大数据块返回。我试图找出如何用其他方法替换属性对象中所有link出现的值,但是我很难理解如何创建可以逐步解决的灵活解决方案放入数组或对象以检查link是否存在。

以下是数据示例:

const data = {
  components: [
    {
      name: 'header',attributes: {
        messageBars: [],link: '/link/'
        navigation: {
          brand: {
            link: '/',alt: 'blah',},{
      name: 'body',attributes: {
        header: {
          text: 'blah',buttons: [
          {
            children: 'OK!',link: '/link/',],

我已经深入到属性层,并且陷入了如何创建称为readData的递归函数的问题。

const replaceLink = (newLink: string,data: object) => {
  data.components.forEach(component => {
     if(component.attributes) readData(component.attributes,newLink);
  });

  return data;
};

解决方法

我知道,这有点厚脸皮,但是您也可以通过将对象结构转换为JSON,替换链接然后再次将其转换回来完成整个工作:

const data = {
  components: [
    {
      name: 'header',attributes: {
        messageBars: [],link: '/link/',navigation: {
          brand: {
            link: '/',alt: 'blah',},{
      name: 'body',attributes: {
        header: {
          text: 'blah',buttons: [
          {
            children: 'OK!',],]
};



const changeLinks=newlink=>JSON.parse(JSON.stringify(data).replace(/"link":"[^"]*"/g,'"link":"'+newlink+'"'))

console.log(changeLinks("abc"))

,

如果您只想找到存在的链接。这会打印出数据中的所有链接。

const data = {
  components: [{
      name: 'header',alt: 'blah'
          }
        }
      }
    },attributes: {
        header: {
          text: 'blah'
        },buttons: [{
          children: 'OK!',link: '/link/'
        }]
      }
    }
  ]
}
const findLinks = (elem) => {

  if (Array.isArray(elem)) {
    elem.forEach(e => findLinks(e))
  } else if (elem instanceof Object) {
    if (elem.hasOwnProperty('link')) {
      console.log('link found',elem.link,elem)
    }
    for (const key in elem) {
      findLinks(elem[key])
    }
  }
}
findLinks(data)

,

这是递归执行此操作的一种方法。它比我希望的要混乱一些,但是它确实可以完成工作,我希望它理解起来也不会太难。如果值是一个数组,它将为数组的每个项目调用自身。如果它是一个非数组对象,它将用键“ link”替换任何值,否则将对所有值进行递归调用。对于原始值(非对象),它们保持不变。

请注意,如果有一个保存对象或数组的“链接”键(这将替换整个对象/数组,而不是任何递归的内容),则此行为可能不会达到预期的效果-我假设您知道不会发生,但是如果是这样的话,适应它应该不难。

const data = {
  components: [
    {
      name: 'header',]
};

const replaceLink = (newLink,value) => {
  if (Array.isArray(value)) {
    return value.map(item => replaceLink(newLink,item));
  }
  else if (value instanceof Object) {
    const replacement = { ...value };
    for (const key in replacement) {
      if (key === 'link') {
        replacement[key] = newLink;
      }
      else {
        replacement[key] = replaceLink(newLink,replacement[key]);
      }
    }
    return replacement;
  }
  return value;
};

const newData = { components: replaceLink('replacement link',data.components) };

console.log(newData);

,

您也可以这样做

const data = {
  components: [{
      name: 'header',link: '/link/'
        }]
      }
    }
  ]
}

function replaceLink(newLink,object) {
  if (Array.isArray(object)) {
    object.forEach(item => {
      if (Object.prototype.toString.call(item) === '[object Object]' || Array.isArray(item)) {
        replaceLink(newLink,item);
      }
    });
  } else {
    for (item in object) {
      if (item == "link") {
        object[item] = newLink;
      }
      if (Object.prototype.toString.call(object[item]) === '[object Object]' || Array.isArray(object[item])) {
        replaceLink(newLink,object[item]);
      }
    }
  }
}

replaceLink("newLink",data);

console.log(data);

,

我发现将递归遍历和对象转换与您要执行的操作的细节区分开来是有帮助的。在这里,我编写了一个辅助函数replaceVal,该函数遍历一个对象并使用每个嵌套的键/值对调用回调,从而使您可以对值进行所需的任何转换。

然后,我们可以根据需要编写一个replaceLink函数。对我来说,您替换链接实际上要做什么并不清楚。我写了一个带有回调的版本,该回调检查键是否为"link"且值是否为String,并通过将现有值的大写版本附加到固定前缀来创建更新后的值。但是您可以在这里做任何您需要的事情。

// helper function
const replaceVal = (f) => (o) =>
  Array .isArray (o) 
    ? o .map (replaceVal (f))
  : Object (o) === o
    ? Object .fromEntries (Object .entries (o) .map (([k,v]) => [k,replaceVal (f) (f(k,v))]))
    : o

// main function
const replaceLink = replaceVal (
  (k,v) => k == "link" && String(v) === v ? `new/path/to${v.toUpperCase()}` : v
)

// test data
const data = {components: [{name: "header",attributes: {messageBars: [],link: "/link/",navigation: {brand: {link: "/",alt: "blah"}}}},{name: "body",attributes: {header: {text: "blah"},buttons: [{children: "OK!",link: "/link/"}]}}]}

// demo
console .log (replaceLink (data))
.as-console-wrapper {max-height: 100% !important; top: 0}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-