【问题标题】:I have an array of 100 objects with properties of category and subcategory and need to create a new array of the count of subcategories?我有一个包含 100 个具有类别和子类别属性的对象的数组,并且需要创建一个包含子类别计数的新数组?
【发布时间】:2016-01-12 23:08:54
【问题描述】:

我有一个包含 100 个具有类别和子类别属性的对象的数组,我想创建一个新数组,其中包含每个类别的名称和该类别的子类别的数量(计数)?

数组示例:

[{
    ticketId: 1,
    Category: "Driver",
    CategoryID: 29,
    SubCategory: "Monitor",
    SubCategoryID: 31
}, {
    ticketId: 2,
    Category: "Driver",
    CategoryID: 29,
    SubCategory: "Monitor",
    SubCategoryID: 31
}, {
    ticketId: 3,
    Category: "Hardware",
    CategoryID: 11,
    SubCategory: "Monitor",
    SubCategoryID: 32
}, {
    ticketId: 4,
    Category: "Hardware",
    CategoryID: 11,
    SubCategory: "phone",
    SubCategoryID: 13
}];

类别列表示例:

[{
    "ID": 1,
    "ParentID": 0,
    "Name": "Printing"
}, {
    "ID": 2,
    "ParentID": 1,
    "Name": "Toner"
}, {
    "ID": 3,
    "ParentID": 1,
    "Name": "Power"
}, {
    "ID": 4,
    "ParentID": 1,
    "Name": "Paper Jam"
}, {
    "ID": 5,
    "ParentID": 0,
    "Name": "Office Applications"
}]

父 ID 为 0 为类别,任何其他数字为子类别

【问题讨论】:

  • 你可以使用某种地图并减少
  • 是类别,嵌套在 JSON 对象中还是单独的数组中?
  • 类别在不同的数组中
  • 以我上面使用的例子我想说类别:硬件2子类别:电话1
  • 两个数组如何映射在一起?

标签: javascript angularjs


【解决方案1】:

也许这对你有用。它利用Array.prototype.reduce()

var data = [{ ticketId: 1, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 2, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 3, Category: "Hardware", CategoryID: 11, SubCategory: "Monitor", SubCategoryID: 32 }, { ticketId: 4, Category: "Hardware", CategoryID: 11, SubCategory: "phone", SubCategoryID: 13 }],
    count = data.reduce(function (r, a) {
        r[a.Category] = r[a.Category] || {};
        r[a.Category][a.SubCategory] = (r[a.Category][a.SubCategory] || 0) + 1;
        return r;
    }, {});

document.write('<pre>' + JSON.stringify(count, 0, 4) + '</pre>');

只是Category 中的计数:

var data = [{ ticketId: 1, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 2, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 3, Category: "Hardware", CategoryID: 11, SubCategory: "Monitor", SubCategoryID: 32 }, { ticketId: 4, Category: "Hardware", CategoryID: 11, SubCategory: "phone", SubCategoryID: 13 }],
    count = data.reduce(function (r, a) {
        r[a.Category] = (r[a.Category] || 0) + 1;
        return r;
    }, {});

document.write('<pre>' + JSON.stringify(count, 0, 4) + '</pre>');

【讨论】:

  • 感谢您抽出宝贵时间回复。您对 Array.prototype.reduce() 的读数有什么建议吗?
  • 首先看一下语言规范是一件好事,无论是 ecma 标准还是 mdn,就像上面的链接。然后我会在这个网站上搜索 javascript 并减少(没有和)。但处理它的最好方法是尝试用它来测试自己的想法。
  • 我没有意识到您已经有了文档链接。很抱歉让你重复自己。我非常感谢您所表现出的患者和理解。非常感谢!!!
  • 虽然他没有说出来,但 OP 需要两个计数出现在同一个结构中,而这段代码并不能真正起作用。
  • @Alnitak,这可能是真的,但示例列表中没有 monitor 的类别或任何它映射到的部分。我在问这个问题,但没有得到关于类别的任何答案。那么,处理它的正确方法是什么?
【解决方案2】:

reduce:每个类别的第一个子类别数:

var subcategoriesCounts = subcats.reduce(function(acc, cur) {
    acc[cur.CategoryID] = (acc[cur.CategoryID] || 0) + 1;
    return acc;
}, {});

然后使用map 将categories 转换为所需的对象:

var result = categories.map(function(cat) {
    return {
        name: cat.Name,
        count: subcategoriesCounts[cat.ID] || 0
    }
});

【讨论】:

    【解决方案3】:

    var arr = [{ ticketId: 1, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 2, Category: "Driver", CategoryID: 29, SubCategory: "Monitor", SubCategoryID: 31 }, { ticketId: 3, Category: "Hardware", CategoryID: 11, SubCategory: "Monitor", SubCategoryID: 32 }, { ticketId: 4, Category: "Hardware", CategoryID: 11, SubCategory: "phone", SubCategoryID: 13 } ];
    
    var map = {}
    
    
    for(var i = 0; i < arr.length; i++) {
      console.log(arr[i])
        if (!map[arr[i].Category]) {
          map[arr[i].Category] = {
            count: 1,
            parentId: arr[i].CategoryID,
            categoryId: arr[i].SubCategoryID,
            categoryName: arr[i].SubCategory
          };
        } else {
          map[arr[i].Category].count++;
        }
    }
    
    var results = [];
    for (var category in map) {
      results.push(map[category]);
    }
    
    var el = document.getElementById("result").innerHTML = JSON.stringify(results, null, '  ')
    &lt;pre id="result"&gt;&lt;/pre&gt;

    【讨论】:

      【解决方案4】:

      //格式化

      var list = [
          {
              "ticketID": 1, 
              "category": "driver", 
              "subcategories": ['toner','power','paper jam','office applications']
          },
          {
              "ticketID": 2, 
              "category": "driver", 
              "subcategories": ['toner','power']
          },
      ];
      

      然后你可以简单地得到潜艇的长度 console.log(list[0].subcategories.length)

      以及访问它们 console.log(list[0].subcategories[0])

      【讨论】:

      • 我现在肯定明白你在说什么。感谢您花时间展示示例。我将不得不在命令链上运行它,看看我们是否可以修改那个 API,一旦我向他们解释了你的例子,这应该不是问题。感谢您抽出宝贵时间回复!!!
      • 我一定会的。我实际上是在我们说话的时候写电子邮件。更好的实施总是受到赞赏并有助于提高效率。谢谢@jordan davis
      【解决方案5】:

      要将两个级别的计数组合在同一结构中,您必须将计数与子级分开。如果您既将顶级计数存储为属性,又将子级本身存储为属性,这将导致无穷无尽的混乱。

      一个更好的结构由此产生:

      var counts = data.reduce(function(r, o) {
          var cat = o.Category;
          var sub = o.SubCategory;
      
          r[cat] = r[cat] || { count: 0, children: {} }
          r[cat].count++;
      
          r[cat].children[sub] = r[cat].children[sub] || { count: 0 }
          r[cat].children[sub].count++;
          return r;
      }, {});
      

      将为您的数据生成:

      {
        "Driver": {
          count: 2,
          children: {
              "Monitor": { count: 2 }
          },
        },
        "Hardware": {
          count: 2,
          children: {
            "Monitor": { count: 1},
            "phone": { count: 1 },
          }
        }
      }
      

      如果需要,它支持额外的嵌套级别。

      【讨论】:

        猜你喜欢
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 2020-11-20
        • 2022-09-30
        • 2019-12-15
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        相关资源
        最近更新 更多