【问题标题】:NodeJS - flatten nested array in recursion into an array of stringsNodeJS - 以递归方式将嵌套数组展平为字符串数组
【发布时间】:2021-08-21 09:39:48
【问题描述】:

我有这个数据结构:

{
  "fieldNodes": [
    {
      "selectionSet": {
        "selections": [
          {
            "name": {
              "value": "id"
            }
          },
          {
            "name": {
              "value": "phone"
            }
          },
          {
            "name": {
              "value": "address"
            },
            "selectionSet": {
              "selections": [
                {
                  "name": {
                    "value": "street"
                  }
                },
                {
                  "name": {
                    "value": "city"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

我需要以递归方式遍历 fieldNodes 数组,并创建一个包含其值的字符串数组 (name.value)。

嵌套值将由一个点 ("address.city") 表示。

此示例的结果将是:["id", "phone", "address. street", "address.city"]

我假设我在 fieldNodes 数组中有一个对象。

有人可以帮我看看 NodeJS 中的代码应该是什么样子吗?

【问题讨论】:

标签: javascript node.js arrays recursion


【解决方案1】:

试试我做的这个递归函数:

var obj = {
  "fieldNodes": [{
    "selectionSet": {
      "selections": [{
          "name": {
            "value": "id"
          }
        },
        {
          "name": {
            "value": "phone"
          }
        },
        {
          "name": {
            "value": "address"
          },
          "selectionSet": {
            "selections": [{
                "name": {
                  "value": "street"
                }
              },
              {
                "name": {
                  "value": "city"
                }
              }
            ]
          }
        }
      ]
    }
  }]
};

function flatten(obj) {
  if (!obj.selectionSet) {
    if (obj.name) return [obj.name.value];
    return [];
  }
    
  var list = obj.selectionSet.selections.map(flatten).flat();
  if (!obj.name) return list;
  return list.map(item => obj.name.value + "." + item);
}

var list = obj.fieldNodes.map(flatten).flat();
console.log(list);

【讨论】:

    【解决方案2】:

    您可以使用递归生成器函数:

    var data = {'fieldNodes': [{'selectionSet': {'selections': [{'name': {'value': 'id'}}, {'name': {'value': 'phone'}}, {'name': {'value': 'address'}, 'selectionSet': {'selections': [{'name': {'value': 'street'}}, {'name': {'value': 'city'}}]}}]}}]}
    function* flatten(d, c = []){
        for (var i of d){
           if ("selectionSet" in i){
               yield* flatten(i.selectionSet.selections, 'name' in i ? [...c, i.name.value] : c)
           }
           else{
              yield [...c, i.name.value]
           }
        }
    }
    var result = Array.from(flatten(data.fieldNodes)).map(x => x.join('.'));
    console.log(result)

    【讨论】:

      【解决方案3】:

      一旦下降到selectionSort 级别,这是一个相当简单的递归。在这里,我们将递归调用包装成一个 (flat)maps 覆盖 fieldNodes 对象。既然你只期待一个,那么我们这里map还是flatMap都无所谓,这个结果更简单。但是,如果您可能有多个,并且希望将它们分组,则可以将 fieldNodes .flatMap (...) 替换为 fieldNodes .map (...)

      const processSelectionSet = ({selectionSet: {selections = []}}) =>
        selections.flatMap (
          ({name: {value}, selectionSet}) => selectionSet 
            ? processSelectionSet ({selectionSet}) .map (name => `${value}.${name}`)
            : value
        )
      
      const extract = ({fieldNodes = []}) => 
        fieldNodes .flatMap (processSelectionSet)
      
      const input = {fieldNodes: [{selectionSet: {selections: [{name: {value: "id"}}, {name: {value: "phone"}}, {name: {value: "address"}, selectionSet: {selections: [{name: {value: "street"}}, {name: {value: "city"}}]}}]}}]}
      
      console .log (extract (input))

      主函数processSelectionSort 简单地对selections 进行平面映射,如果没有selectionSort 子节点,则捕获返回的名称/值,或者将其与对该子节点的递归调用的结果合并,如果它存在。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-15
        • 1970-01-01
        • 1970-01-01
        • 2015-02-02
        • 1970-01-01
        相关资源
        最近更新 更多