【问题标题】:Recursive data in JSON objectJSON对象中的递归数据
【发布时间】:2020-05-30 09:59:47
【问题描述】:
{
"groups": [
    {
        "name": "Event",
        "groups": [
            {
                "name": "Service",
                "subscriptions": [
                    {
                        "topic": "SERVICE_STATUS_PRESETS"
                    },
                    {
                        "topic": "AIRCRAFT_ACTIVATION",

                    },
                    {
                        "topic": "OUT_OF_SERVICE",

                    }
                ]
            }
        ]
    },
    {
        "name": "Enquiries",
        "groups": [
            {
                "name": "Service-related",
                "subscriptions": [
                    {

                        "topic": "PROMO_CODES_REQUESTS",

                    }
                ]
            }
        ]
    }
],
"subscriptions": [
    {
        "topic": "BANNERS",
    },
    {
        "topic": "DOCUMENTS",
    },
    {
        "topic": "USER",
    }
]

}

好的,伙计们,我有这样的 JSON 结构,我需要的是:返回数组中的所有主题,在这个例子中它将是:

[“SERVICE_STATUS_PRESETS”、“AIRCRAFT_ACTIVATION”、“OUT_OF_SERVICE”、“PROMO_CODES_REQUESTS”、“BANNERS”、“DOCUMENTS”、“USER”]

我尝试这样的递归调用,虽然我只得到最后三个记录:

getRecursive() {
if (Array.isArray(data)) {
       for (let i = 0; i < data.length; i++) {
         if (data[i].subscriptions) {
           return data[i].subscriptions.map((val: SubscriptionGroupDetails) => val.topic);
         } else if (data[i].groups) {
           return this.getAllTopics(data[i].groups);
         }
       }
     }
     if (data && data.groups) {
      return this.getAllTopics(data.groups);
     }
     return data.subscriptions.map((val: SubscriptionGroupDetails) => val.topic);
}

【问题讨论】:

  • @Teemu:这看起来并不特别相关。
  • @ScottSauyet 也许不是,但在提供的示例中没有递归(至少很明显),也许链接帖子中的答案给出了一些想法。

标签: javascript arrays json object recursion


【解决方案1】:

您可以采用递归方法并检查

  • 如果传递过来的数据不是检查对象,则返回空数组,
  • 如果对象有想要的属性,则返回一个值为topic的数组,
  • 或获取值并使用函数进行递归调用,并返回一个包含结果的数组。

function getTopics(object) {
    if (!object || typeof object !== 'object') return [];
    if ('topic' in object) return [object.topic];
    return Object.values(object).reduce((r, v) => [...r, ...getTopics(v)], []);
}

var data = { groups: [{ name: "Event", groups: [{ name: "Service", subscriptions: [{ topic: "SERVICE_STATUS_PRESETS" }, { topic: "AIRCRAFT_ACTIVATION" }, { topic: "OUT_OF_SERVICE" }] }] }, { name: "Enquiries", groups: [{ name: "Service-related", subscriptions: [{ topic: "PROMO_CODES_REQUESTS" }] }] }], subscriptions: [{ topic: "BANNERS" }, { topic: "DOCUMENTS" }, { topic: "USER" }] },
    result = getTopics(data);

console.log(result);

【讨论】:

    【解决方案2】:

    这是使用object-scan的解决方案

    // const objectScan = require('object-scan');
    
    const data = {"groups":[{"name":"Event","groups":[{"name":"Service","subscriptions":[{"topic":"SERVICE_STATUS_PRESETS"},{"topic":"AIRCRAFT_ACTIVATION"},{"topic":"OUT_OF_SERVICE"}]}]},{"name":"Enquiries","groups":[{"name":"Service-related","subscriptions":[{"topic":"PROMO_CODES_REQUESTS"}]}]}],"subscriptions":[{"topic":"BANNERS"},{"topic":"DOCUMENTS"},{"topic":"USER"}]};
    
    const searchTopics = (obj) => objectScan(['**.topic'], { rtn: 'value' })(obj);
    
    console.log(searchTopics(data));
    /* => [
      'USER',
      'DOCUMENTS',
      'BANNERS',
      'PROMO_CODES_REQUESTS',
      'OUT_OF_SERVICE',
      'AIRCRAFT_ACTIVATION',
      'SERVICE_STATUS_PRESETS'
    ] */
    .as-console-wrapper {max-height: 100% !important; top: 0}
    &lt;script src="https://bundle.run/object-scan@13.7.1"&gt;&lt;/script&gt;

    免责声明:我是object-scan的作者

    【讨论】:

      【解决方案3】:

      如果您有兴趣,此版本将采用功能方法。上面还有其他的,但这只是另一种看待它的方式。

      const recursion = object => Object.entries(object).map(([a, b]) => {
        if (a === 'topic') return b;
        if (Array.isArray(b)) return b.map(recursion);
        return [];
      }).flat(Infinity);
      
      recursion(obj);
      

      【讨论】:

      【解决方案4】:

      编辑:添加了另一种使用 .reduce()

      的方法

      您可以创建一个topics 的空数组,然后递归地浏览嵌套结构,每次遇到它时添加一个主题,使用javascript .forEach() 循环浏览任何嵌套的groupssubscriptions .

      let topics = [];
      
      let findTopics = obj => {
         if (obj.groups) {
            obj.groups.forEach(findTopics);
         }
         if (obj.subscriptions) {
            obj.subscriptions.forEach(findTopics);
         }
         if (obj.topic) {
            topics.push(obj.topic);
         }
      }
      
      findTopics(data);
      

      或者使用.reduce() 的一种可能更简洁的方式:

      let findTopicsRecursive = (topics, obj) => {
         if (obj.groups) {
            topics = obj.groups.reduce(findTopicsRecursive, topics);
         }
         if (obj.subscriptions) {
            topics = obj.subscriptions.reduce(findTopicsRecursive, topics);
         }
         if (obj.topic) {
            topics.push(obj.topic);
         }
         return topics;
      }
      
      let findTopics = data => findTopicsRecursive([], data);
      
      let topics = findTopics(data);
      

      【讨论】:

      • @YosefTukachinsky 你的意思是说这段代码非常依赖特定的数据结构?
      • 是的,这就是我的意思
      • @calarin:查看其他一些答案,了解更通用的技术。
      • @scottsauyet YosefTukachinsky 是的,我明白你的意思!
      【解决方案5】:

      使用这个:

      function getTopics(obj){
         if(typeof obj !== 'object') return [];
         if(obj.topic) return [obj.topic];
         var res = [];
         for(var i in obj){
           res.push(...getTopics(obj[i]));
         }
         return res;
      }
      

      工作示例:

      const topics = {
      "groups": [
          {
              "name": "Event",
              "groups": [
                  {
                      "name": "Service",
                      "subscriptions": [
                          {
                              "topic": "SERVICE_STATUS_PRESETS"
                          },
                          {
                              "topic": "AIRCRAFT_ACTIVATION",
      
                          },
                          {
                              "topic": "OUT_OF_SERVICE",
      
                          }
                      ]
                  }
              ]
          },
          {
              "name": "Enquiries",
              "groups": [
                  {
                      "name": "Service-related",
                      "subscriptions": [
                          {
      
                              "topic": "PROMO_CODES_REQUESTS",
      
                          }
                      ]
                  }
              ]
          }
      ],
      "subscriptions": [
          {
              "topic": "BANNERS",
          },
          {
              "topic": "DOCUMENTS",
          },
          {
              "topic": "USER",
          }
      ]
      }
      
      function getTopics(obj){
        if(typeof obj !== 'object') return [];
        if(obj.topic) return [obj.topic];
        var res = [];
        for(var i in obj){
          res.push(...getTopics(obj[i]));
        }
        return res;
      }
      
      
      console.log(getTopics(topics));

      【讨论】:

        猜你喜欢
        • 2014-11-08
        • 2013-12-02
        • 2017-03-26
        • 2014-04-08
        • 2019-09-03
        • 2016-10-17
        • 2015-06-04
        • 1970-01-01
        • 2021-10-10
        相关资源
        最近更新 更多