【问题标题】:How to recursively traverse array and replace certain values? [duplicate]如何递归遍历数组并替换某些值? [复制]
【发布时间】:2022-01-15 05:09:36
【问题描述】:

我正在尝试解析 JSON 结构,json 结构看起来像这样:

{
    children: [
        {
            type: "p",
            children: [{
                text: ""
            }]
        },
        {
            type: "social_embed",
            children: [{
                text: ""
            }]
            source_url: "some_url"
        },
        {
            type: "p",
            children: [{
                type: "p",
                children: [{
                    type: "p",
                    children: [{
                        text: ""
                    }]
                }]
            }]
        },
    ]
}

输出将如下所示:

{
    children: [
        {
            type: "p",
            children: [{
                text: ""
            }]
        },
        {
            type: "p",
            children: [{
                text: "some_url"
            }]
        },
        {
            type: "p",
            children: [{
                type: "p",
                children: [{
                    type: "p",
                    children: [{
                        text: ""
                    }]
                }]
            }]
        },
    ]
}

这是我正在尝试的代码:

 if (currentBlock.type == "card" || currentBlock.type =="card_body") 
       {
          parsedBlocks.map((block: any, index: any) => {
            block.children = parseBlocks(block.children)
          })

          console.log("Blocks after parsing", parsedBlocks)

          editor.insertFragment(parsedBlocks);
          return true
        }

        const parseBlocks = (blocks: any): any => {

        blocks.forEach((block: any) => {
          console.log("Block ", block)
          if (block.type == "social_embed") {
            const newBlock = {
                type: "p",
                children: [
                  {
                    text: block.source_url
                  }
                ]
              }
              blocks[blocks.indexOf(block)] = newBlock
          }
          if (block.children) {
            return parseBlocks(block.children)
          }
        })
        return blocks
      }

我想递归遍历所有子对象,直到对象中没有子属性,当我遇到类型为“social_embed”的对象时,我想将其替换为类型:“p”并将文本替换为 source_url 并修改整个数组,孩子们可以有无限的嵌套,但 social_embed 除了 {text: ""}

之外,它的孩子们里面不能有任何东西

【问题讨论】:

  • 你有一些代码,你试过了吗?出了什么问题?
  • @NinaScholz 是的,我将其添加到问题中
  • 在阳光下,JavaScript 并没有什么新鲜事。这回答了你的问题了吗? stackoverflow.com/questions/15690706/…
  • 您有想要的结果吗? “修改整个数组”是什么意思
  • @JamieDixon 是的

标签: javascript arrays recursion


【解决方案1】:

类似于 Nina 和 Jamie 的方法,但编写方式略有不同:

const transform = ({type, children = [], source_url, ...rest}) =>
  type == 'social_embed'
    ? {type:'p', children: [{text: source_url}]}
    : {type, ...rest, ...(children.length ? {children : children .map (transform)} : {})}

const input = {children: [{type: "p", children: [{text: ""}]}, {type: "social_embed", children: [{text: ""}], source_url: "some_url"}, {type: "p", children: [{type: "p", children: [{type: "p", children: [{text: ""}]}]}]}]}

console .log (transform (input))
.as-console-wrapper {max-height: 100% !important; top: 0}

【讨论】:

    【解决方案2】:

    这样的事情怎么样:

    const parse = node => {
      if (node.type === "social_embed") {
        return {
          type: "p",
          children: [{ text: node.source_url}]
        }
      }
    
      return node.children ? {
        ...node,
        children: node.children.map(parse)
      } : node;
    }
    

    https://replit.com/@jamiedixon/ParseTree#index.js

    如果您想更进一步,您可以根据type 定义节点的访问者并以这种方式处理它们。

    const socialEmbed = node => ({
      type: "p",
      children: [{ text: node.source_url }]
    })
    
    const visitors = {
      "social_embed": [socialEmbed]
    }
    
    const parse = node => {
      const _visitors = visitors[node.type] || [x => x];
      const result = _visitors.reduce((agg, fn) =>  fn(agg), node);
    
      return result.children ? {
        ...result,
        children: result.children.map(parse)
      } : result;
    }
    

    https://replit.com/@jamiedixon/ParseTree#visitors.js

    【讨论】:

      【解决方案3】:

      你可以做一个递归函数循环遍历你的树并在遇到social_embed时就地修改

      const input = {children: [{type: "p",children: [{text: ""}]},{type: "social_embed",children: [{text: ""}], source_url: "some_url"},{type: "p",children: [{type: "p",children: [{type: "p",children: [{text: ""}]}]}]}]}
      
      function rec(input) {
          if (input.type === "social_embed") {
              input.children = [{text: input.source_url}]
              input.type = "p"
              delete input.source_url
          }
          input.children?.forEach(rec)
      }
      rec(input)
      
      console.log(JSON.stringify(input, null, 4))
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      如果您希望生成一个新对象并保持原始对象不变,您可以这样做

      const input = {children: [{type: "p",children: [{text: ""}]},{type: "social_embed",children: [{text: ""}], source_url: "some_url"},{type: "p",children: [{type: "p",children: [{type: "p",children: [{text: ""}]}]}]}]}
      
      function rec(input) {
        const output = {...input}
          if (input.type === "social_embed") {
              output.children = [{text: input.source_url}]
              output.type = "p"
          delete output.source_url
          } else if (input.children) {
          output.children = input.children.map(rec)
        }
        return output
      }
      const output = rec(input)
      
      console.log(JSON.stringify(output, null, 4))
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        【解决方案4】:

        您可以将新对象映射到子对象并获取旧对象的新对象。

        const
            update = ({ children = [], ...object }) => {
                if (object.type === "social_embed") {
                    const
                        type= 'p',
                        text = object.source_url;
                    return { type, children: [{ text }] };
                }
                children = children.map(update);
                return children.length
                    ? { ...object, children }
                    : object;
            },
            tree = { children: [{ type: "p", children: [{ text: "" }] }, { type: "social_embed", children: [{ text: "" }], source_url: "some_url" }, { type: "p", children: [{ type: "p", children: [{ type: "p", children: [{ text: "" }] }] }] }] };
        
        tree.children = tree.children.map(update);
        
        console.log(tree);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          • 2019-02-03
          • 1970-01-01
          • 1970-01-01
          • 2015-05-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多