吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 605|回复: 2
收起左侧

[求助] 配置数据,数组转对象的问题

[复制链接]
cqwcns 发表于 2022-11-10 16:03
如下代码,现在有一些配置数,是数组的形式,我需要将它转变为对象。
不知道有什么好的实现方法,请各位大佬指教,感谢。


直接上码:

[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>

    // 原数据是这样的(即下标0为键,下标1为值)
    const arr = [
      ["标题", "这是标题"],
      ["副标题", "这是副标题"],
      ["文字颜色", "white"],
      ["背景颜色", "red"]
    ];

    // 要输出成这样
    // const objConfig = {
    //   title: {
    //     text: "这是标题",
    //     subtext: "这是副标题"
    //   },
    //   color: {
    //     textColor: 'white',
    //     bgColor: 'red'
    //   }
    // }

    // 注意,源数据行的顺序可能会有变化,所以,我考虑可能需要一个枚举来建立关系对应
    const arrConfigList = [
      { name: '标题', target: 'title.text' },
      { name: '副标题', target: 'title.subtext' },
      { name: '文字颜色', target: 'color.textColor' },
      { name: '背景颜色', target: 'color.bgColor' }
    ];

    // 到这里就没有什么思路了...

  </script>
</body>

</html>

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ChengXuHa 发表于 2022-11-10 17:17
[JavaScript] 纯文本查看 复制代码
    let title = {};
    let color = {};
    let list = [];
    arr.map(e => {

        if (e[0] == "标题") {
            title["text"] = e[1]
        }
        else if (e[0] == "副标题") {
            title["subtext"] = e[1]

        }
        else if (e[0] == "文字颜色") {
            color["textColor"] = e[1]
        }
        else {
            color["bgColor"] = e[1]
        }

    })
    list.push({
        title: title,
        color: color
    });
    var obj = JSON.parse(JSON.stringify(list)); //由JSON字符串转换为JSON对象
pansong291 发表于 2022-11-11 23:34
本帖最后由 pansong291 于 2022-11-11 23:37 编辑
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
  <head>
    <meta charset="UTF-8" />
    <title>Data Convertor</title>
  </head>
  <body></body>
  <script>
    // 原数据是这样的(即下标0为键,下标1为值)
    const arr = [
      ['标题', '这是标题'],
      ['副标题', '这是副标题'],
      ['文字颜色', 'white'],
      ['背景颜色', 'red']
    ]

    // 要输出成这样
    // const objConfig = {
    //   title: {
    //     text: "这是标题",
    //     subtext: "这是副标题"
    //   },
    //   color: {
    //     textColor: 'white',
    //     bgColor: 'red'
    //   }
    // }

    // 注意,源数据行的顺序可能会有变化,所以,我考虑可能需要一个枚举来建立关系对应
    const arrConfigList = [
      { name: '标题', target: 'title.text' },
      { name: '副标题', target: 'title.subtext' },
      { name: '文字颜色', target: 'color.textColor' },
      { name: '背景颜色', target: 'color.bgColor' }
    ]

    // 到这里就没有什么思路了...
    const data = convert(arr, arrConfigList)
    console.log(data)
    const pre = document.createElement('pre')
    pre.innerText = JSON.stringify(data, null, 2)
    document.body.append(pre)

    function convert(arr, configList) {
      const mapping = {}
      for (let map of configList) {
        mapping[map.name] = `.${map.target}`
      }
      const result = {}
      for (let item of arr) {
        if (item && item.length && item.length > 1) {
          const path = mapping[item[0]]
          if (path) parsePathOf(result, path, item[1])
        }
      }
      return result
    }

    /**
     * 根据指定的字符串解析对应路径并将指定数据填充到指定对象中。
     * 指定的字符串格式不正确将会抛出异常。
     *
     * @param root 需要填充数据的对象或数组
     * @param pathStr 指定路径的字符串,必须以点号或方括号开头,如 .person.name 或 [0].name
     * @param value 需要填充的数据
     */
    function parsePathOf(root, pathStr, value) {
      let errMsg = 'error: illegal path string: ' + pathStr
      let cur = root
      let path = pathStr
      let reg = /[\[.]/
      while (true) {
        // 检查当前对象是否有值且是否是对象或数组类型
        if (!cur || !(cur instanceof Object)) {
          let deepPath = pathStr.substring(0, pathStr.lastIndexOf(path))
          throw 'error: the value of "<root>' + deepPath + '" is not a(n) object/array'
        }
        // 先查找一次
        let matchArr = path.match(reg)
        // 未找到或者不在首个位置抛异常
        if (!matchArr || matchArr.index !== 0) {
          throw errMsg
        }
        // 去掉第一个符号
        path = path.substring(1)
        // 继续找下一个
        let nextMatch = path.match(reg)
        // 获取当前属性名和下个符号
        let field
        let symbol
        if (nextMatch) {
          field = path.substring(0, nextMatch.index)
          symbol = nextMatch[0]
        } else {
          field = path
          symbol = undefined
        }
        if (matchArr[0] === '[') {
          // 检查一下中括号是否配对
          if (field.charAt(field.length - 1) !== ']') {
            throw errMsg
          }
          // 把属性名最后的 ] 去掉,顺便去掉引号
          field = removeQuote(field.substring(0, field.length - 1))
        }
        // 检查属性名不为空,且不能包含右方括号
        if (!field || field.indexOf(']') >= 0) {
          throw errMsg
        }
        if (symbol === '.') {
          // 点号表示是对象,需要保证当前路径是对象
          if (cur[field] === undefined || cur[field] === null) {
            cur[field] = {}
          }
        } else if (symbol === '[') {
          // 中括号表示是数组,需要保证当前路径是数组
          if (cur[field] === undefined || cur[field] === null) {
            cur[field] = []
          }
        } else {
          // 未找到下个,结束
          cur[field] = value
          break
        }
        // 进入下一次迭代
        cur = cur[field]
        path = path.substring(nextMatch.index)
      }
    }

    /**
     * 如果字符串的首尾都是引号,则去除首尾的引号。检测的引号有单引号、双引号和反引号。
     *
     * @param str 受检字符串
     * @returns {string} 去除首尾引号的字符串或它本身
     */
    function removeQuote(str) {
      let reg = /^(["'`]).*\1$/
      if (reg.test(str)) {
        str = str.substring(1, str.length - 1)
      }
      return str
    }
  </script>
</html>

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
cqwcns + 1 + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 06:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表