【问题标题】:pull property object as parent object拉属性对象作为父对象
【发布时间】:2017-06-05 11:30:11
【问题描述】:

我有这组我无法控制的数据(它在某处托管 API,我无权访问)

let x = [
    {name: "james", age: 10, school: {id:1, name:"London"}},
    {name: "james_2", age: 11, school: {id:1, name:"London"}},
    {name: "john", age: 12, school: {id:2, name:"India"}},
    {name: "johnny", age: 56, school: {id:3, name:"USA"}}
]

如何先分组学校?我需要这样的格式

[{
    id:1,
    name: "London",
    data: [{
        name: "james", age: 10, school: {id:1, name:"London"
    },{name: "james_2", age: 11, school: {id:1, name:"London"}}]
}]

【问题讨论】:

    标签: javascript ecmascript-6 lodash


    【解决方案1】:

    您可以使用_.groupBy() 并将结果映射回数组:

    const data = [{"name":"james","age":10,"school":{"id":1,"name":"London"}},{"name":"james_2","age":11,"school":{"id":1,"name":"London"}},{"name":"john","age":12,"school":{"id":2,"name":"India"}},{"name":"johnny","age":56,"school":{"id":3,"name":"USA"}}];
    
    const result = _(data)
      .groupBy('school.name')
      .map((group) => ({ // or Object.assign({}, group[0].school, { data: group });
        ...group[0].school,
        data: group
      }))
      .value();
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

    您可以在不使用 lodash 的情况下执行相同的操作,只需将 Array#reduceMap 结合使用:

    const data = [{"name":"james","age":10,"school":{"id":1,"name":"London"}},{"name":"james_2","age":11,"school":{"id":1,"name":"London"}},{"name":"john","age":12,"school":{"id":2,"name":"India"}},{"name":"johnny","age":56,"school":{"id":3,"name":"USA"}}];
    
    const result = [...data.reduce((map, item) => {
      const school = map.get(item.school.name) || { // or Object.assign({}, { item.school }, { data: [] })
        ...item.school, data: [] 
      };
      
      school.data.push(item);
      
      map.set(item.school.name, school);
      
      return map;
    }, new Map()).values()]
    
    console.log(result);

    【讨论】:

    • 这是什么? _(数据)
    • group[0].school 为什么在这里使用 [0]?
    • _(data) 启动 lodash 链。 group[0].school 用于从组的第一个元素中获取学校名称和 id。
    • group[0].school 怎么可能是第一个元素?我不明白jsfiddle.net/8y0bjzn9
    • 欢迎 :) 顺便说一句 - 对象 rest/spread 需要一个 babel 插件,所以如果它对你不起作用,请改用 Object#assignObject.assing({}, { item.school }, { data: [] })
    【解决方案2】:

    您可以使用reduce() 方法:

    let data = [
        {name: "james", age: 10, school: {id:1, name:"London"}},
        {name: "james_2", age: 11, school: {id:1, name:"London"}},
        {name: "john", age: 12, school: {id:2, name:"India"}},
        {name: "johnny", age: 56, school: {id:3, name:"USA"}}
    ];
    let schools = data.reduce((acc, x) => {
      // Check if the school already exists
      let school = acc.find(y => y.id === x.school.id);
      if (!school) {
        // If not, the current school is the school of the current person
        school = x.school;
        school.data = [];
        acc.push(school);
      } else {
        // Prevent duplication of school objects with the same id
        x.school = school;
      }
      school.data.push(x);
      return acc;
    }, []);
    console.log(schools);

    【讨论】:

      【解决方案3】:

      您可以将 lodash 库与 groupBy 一起使用

      let x = [
          {name: "james", age: 10, school: {id:1, name:"London"}},
          {name: "james_2", age: 11, school: {id:1, name:"London"}},
          {name: "john", age: 12, school: {id:2, name:"India"}},
          {name: "johnny", age: 56, school: {id:3, name:"USA"}}
      ]
      
      
      var result2 = _.chain(x)
          .groupBy(function(o){return o.school.name})
          .pairs()
          .map(function (currentItem) {
              return _.object(_.zip(["school", "name"], currentItem));
          })
          .value();
      console.log(result2);
      

      检查这个 jsFiddle :- http://jsfiddle.net/6yasy30a/

      【讨论】:

      • 成对?那是为了什么?
      • @AlanJenshen _pairs():- 为对象创建一个键值对的二维数组,例如[[键1,值1],[键2,值2]]。 _.pairs({ '巴尼': 36, '弗雷德': 40 }); // => [['barney', 36], ['fred', 40]](不保证迭代顺序)
      【解决方案4】:

      您可以创建一个散列对象,将每所学校的 id 存储起来,这样您就可以将学生推送给它:

      var hash=x.reduce(function(obj,el){
       (obj[el.school.id]=obj[el.school.id]||{id:el.school.id,name:el.school.name,data:[]}).data.push({name:el.name,age:el.age});
        return obj;
      },{});
      
      var arr=Object.values(hash);
      

      http://jsbin.com/vedajijiye/edit?console

      【讨论】:

        【解决方案5】:

        let x = [
            {name: "james", age: 10, school: {id:1, name:"London"}},
            {name: "james_2", age: 11, school: {id:1, name:"London"}},
            {name: "john", age: 12, school: {id:2, name:"India"}},
            {name: "johnny", age: 56, school: {id:3, name:"USA"}}
        ];
        
        let result = [];
        for(var i = 0; i < x.length; i++) {
          var person = x[i];
          var school = result.find(s => s.id === person.school.id);
          if(!school) {
            school = {
              id: person.school.id,
              name: person.school.name,
              data: []
            };
            result.push(school);
          }
          school.data.push(person);
        }
        
        console.log(result);

        【讨论】:

          【解决方案6】:

          如果 id 不存在,使用 reduce 并简单地将新对象推送到结果数组中,否则只需更新找到的对象中的数据数组

          const myArray = x.reduce((res, data) => {
            const found = res.find(o => o.id === data.school.id);
          
            if (!found) {
              res.push({
                  id: data.school.id,
                  name: data.school.name,
                  data: [data]
              });
            } else {
              found.data.push(data);
            }
            return res;
          }, []);
          
          
          console.log(myArray)
          

          【讨论】:

            猜你喜欢
            • 2017-01-25
            • 1970-01-01
            • 2011-08-24
            • 1970-01-01
            • 1970-01-01
            • 2019-07-22
            • 2015-12-23
            • 2015-06-26
            • 1970-01-01
            相关资源
            最近更新 更多