【问题标题】:Building new JSON from existing one从现有的 JSON 构建新的 JSON
【发布时间】:2016-09-22 07:12:40
【问题描述】:

我想从现有的JSON 中构建一个新的JSON。来源有部分和量规,我不再需要列表。名为“items”的新对象应该有一个项目数组。

最终的 JSON 应该按属性 'name' 排序,看起来像

{
  "items": [
    {
      "id": 10000006,
      "name": "Boah"
    },
    {
      "id": 10000013,
      "name": "Gut"
    },
    {
      "id": 10000003,
      "name": "Ipsum"
    },
    {
      "id": 10000001,
      "name": "Lorem"
    },
    {
      "id": 10000005,
      "name": "Lorum"
    },
    {
      "id": 10000004,
      "name": "Name"
    },
    {
      "id": 10000002,
      "name": "Stet"
    }
  ]
}

为了构建新的 JSON,我得到了这个来源:

{
  "sections": [
    {
      "name": "FooBar",
      "rubrics": [
        {
          "name": "Foo",
          "items": [
            {
              "id": 10000001,
              "name": "Lorem"
            },
            {
              "id": 10000002,
              "name": "Stet"
            },
            {
              "id": 10000003,
              "name": "Ipsum"
            }
          ]
        },
        {
          "name": "Bar",
          "items": [
            {
              "id": 10000004,
              "name": "Name"
            },
            {
              "id": 10000005,
              "name": "Lorum"
            },
            {
              "id": 10000006,
              "name": "Boah"
            }
          ]
        }
      ]
    },
    {
      "name": "BlahBloob",
      "rubrics": [
        {
          "name": "Bla",
          "items": [
            {
              "id": 10000013,
              "name": "Gut"
            }
          ]
        },
        {
          "name": "Bloob",
          "items": [
            {
              "id": 10000014,
              "name": "Name"
            },
            {
              "id": 10000015,
              "name": "Lorem"
            }
          ]
        }
      ]
    }
  ]
}

你怎么看?我怎样才能用普通的JavaScriptTypeScript 做到这一点?

感谢您阅读并有时间回答我的问题。并感谢您提前回复。

【问题讨论】:

    标签: javascript json angular typescript


    【解决方案1】:

    给你。您只需要遍历源的每个部分的每个量规即可获取项目。最后,按项目对项目列表进行排序,就完成了。

    此示例使用 ES6 语法,但如果需要,可以轻松将其转换为 ES5。

    function extractItems(source) {
      const items = [];
    
      for (const section of source.sections) {
        for (const rubric of section.rubrics) {
          items.push(...rubric.items);
        }
      }
    
      items.sort((a, b) => a.name.localeCompare(b.name));
    
      return { items };
    }
    

    【讨论】:

    • 关于您对 rubric.items 进行迭代的编辑,这不是必需的,但这取决于您的浏览器/nodejs 版本。语法items.push(...rubric.items) 被称为“扩展运算符”,工作正常,但它是引擎实现的最新 ES6 特性之一。我将实现更改为使用.concat。它避免了额外的 for 循环,并且在性能方面更有效:)
    • 我喜欢函数式编程!这是我的首选版本。在处理大数据时,我经常使用 for 循环,而且速度更快(map 创建一个新数组并填充它,而 for 循环只是遍历初始数组)。但是对于普通的数组(数以千计的项目)来说,它是完美的!
    • @AurélienRibon 我不得不同意您的解决方案更快并且使用更少的内存。阅读时也会更容易理解。 :)
    • 视情况而定。我真的很喜欢函数式编程,所以我会更快地阅读你的,但这确实需要一些练习。命令式编程更常见(取决于用户背景),但它也更冗长和缩进。在这个简单的算法中,没关系,但你经常将函数分解为多个子函数......
    • 另外,函数式编程的一大优势是它依赖于函数。 V8(chrome,nodejs)一旦经常调用(超过2次)就对函数进行大量优化。如果我的extractItems 函数只在超大数组上调用一次,它会很慢。如果你在同一个数组上调用它 3 次,第三次会快 10 到 100 倍。曲轴/涡轮风扇优化器的魔力:)
    【解决方案2】:

    更实用的方法是使用 ma​​preduce 来挑选和合并它们。

    data.sections
      .map(section => section.rubrics) // get rubrics
      .reduce((a, b) => a.concat(b)) // merge rubrics
      .map(rubric => rubric.items) // get items from each rubric
      .reduce((a, b) => a.concat(b)) // merge items
      .sort((a, b) => a.name.localeCompare(b.name)); // sort
    

    【讨论】:

    • 这很优雅。非常感谢你。我认为这是正确的答案。
    【解决方案3】:
    function(oldObj) {
        var newObj = {
            "items": []
        };
    
        oldObj.sections.forEach(function(section) {
            section.rubrics.forEach(function(rubric) {
                rubric.items.forEach(function(item) {
                    newObj.items.push(item);
                });
            });
        });
    
        newObj.items = newObj.items.sort(function(a, b) {
            if (a.name < b.name) { return -1; }
            if (a.name > b.name) { return 1;  }
            return 0;
        });
        return newObj;
    }
    

    并且只需使用JSON.parse()JSON.stringify() 将JSON 转换为对象。

    【讨论】:

    • 是的!这是开箱即用的。谢谢!只是更喜欢@Aurélien Ribon 的 ES6 语法解决方案。
    【解决方案4】:

    也许对你有帮助

    var data ={
    	"sections": [
    {
    "name": "FooBar",
    "rubrics": [{"name": "Foo", "items": [{"id": 10000001,"name": "Lorem"}, {"id": 10000002,"name": "Stet"}, {"id": 10000003,"name": "Ipsum"}]
    }, {
    			"name": "Bar",
    			"items": [{
    				"id": 10000004,
    				"name": "Name"
    			}, {
    				"id": 10000005,
    				"name": "Lorum"
    			}, {
    				"id": 10000006,
    				"name": "Boah"
    			}]
    		}]
    	}, {
    		"name": "BlahBloob",
    		"rubrics": [{
    			"name": "Bla",
    			"items": [{
    				"id": 10000013,
    				"name": "Gut"
    			}]
    		}, {
    			"name": "Bloob",
    			"items": [{
    				"id": 10000014,
    				"name": "Name"
    			}, {
    				"id": 10000015,
    				"name": "Lorem"
    			}]
    		}]
    	}]
    };
    var itemObj = {};
    var itemArr = [];
    var sections = data.sections;
    for(var i=0;i<sections.length;i++)
    {	
      for(var j=0;j<sections[i].rubrics.length;j++){    
        for(var k=0;k<sections[i].rubrics[j].items.length;k++){      
          var itemObj;
          itemObj['id'] = sections[i].rubrics[j].items[k].id;
          itemObj['name'] = sections[i].rubrics[j].items[k].name;      
          itemArr.push(itemObj);
        }
      }
    }
    var finalObj = {"items":itemArr};
    console.log(finalObj);

    JSFiddle

    【讨论】:

    • 感谢您的努力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多