【问题标题】:Multi level grouping and populate arrays with using lodash使用 lodash 进行多级分组和填充数组
【发布时间】:2022-01-05 16:17:10
【问题描述】:

我正在查看以下示例lodash - group and populate arrays

但是我需要多次分组,如下例所示。我该怎么办?谢谢

    [
      { birthdate: "1993", day: "12", category: "a", name: "Ben" },
      { birthdate: "1993", day: "13", category: "a", name: "John" },
      { birthdate: "1993", day: "14", category: "b", name: "Larry" },
      { birthdate: "1994", day: "15", category: "", name: "Nicole" },        
    ];

[
  {
    birthdate: "1993",
    birthdateDetail: [
      {
        category: "a",
        categoryDetail: [
          { day: "12", name: "Ben" },
          { day: "13", name: "John" },
        ],
      },
      {
        category: "b",
        categoryDetail: [{ day: "14", name: "Larry" }],
      },
    ],
  },
  {
    birthdate: "1994",
    birthdateDetail: [{ category: "", day: "15", name: "Nicole" }],
  },
];

【问题讨论】:

  • 看起来数据的结构会根据是否有多个具有相同类别/详细信息的项目而变化。这是故意的吗?如果您的数据具有一致的结构,生活通常会更轻松

标签: javascript lodash


【解决方案1】:

您可以使用抽象方法进行嵌套分组,方法是获取一个对象,该对象保留每个级别的键以及所需的结果结构。

这种方法适用于任意嵌套。

const
    data = [{ birthdate: "1993", day: "12", category: "a", name: "Ben" }, { birthdate: "1993", day: "13", category: "a", name: "John" }, { birthdate: "1993", day: "14", category: "b", name: "Larry" }, { birthdate: "1994", day: "15", category: "", name: "Nicole" }],
    groups = ['birthdate', 'category'],
    getEmpty = () => ({ _: [] }),
    result = data
      .reduce((q, o) => {
          groups
              .reduce((r, k) => {
                  const v = o[k];
                  if (!v) return r;
                  if (!r[v]) r._.push({ [k]: v, [k + 'Detail']: (r[v] = getEmpty())._ });
                  return r[v];
              }, q)
              ._
              .push(o);
          return q;
      }, getEmpty())
      ._;

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    您的方向正确:使用_.groupBy 将帮助您对数据进行分组,但由于您需要两层嵌套,因此您需要运行两次:

    1. 顶层是按birthdate分组
    2. 第二级是按category分组

    由于_.groupBy returns an object,我们需要使用Object.entries 将键值对转换为符合您预期形状的对象数组。

    在第二级,我们需要进行最后一次迭代,以确保我们从嵌套数据中删除 categorybirthday 键。

    请参阅下面的概念验证:

    const data = [
      { birthdate: "1993", day: "12", category: "a", name: "Ben" },
      { birthdate: "1993", day: "13", category: "a", name: "John" },
      { birthdate: "1993", day: "14", category: "b", name: "Larry" },
      { birthdate: "1994", day: "15", category: "", name: "Nicole" },        
    ];
    
    // Top level: group by birthdate
    const dataByBirthdate = _.groupBy(data, d => d.birthdate);
    
    // Convert object into array of objects
    const transformedData = Object.entries(dataByBirthdate).map(entry => {
      const [birthdate, value] = entry;
    
      // Second level: group by category
      const birthdatedetailByCategory = _.groupBy(value, d => d.category);
      const birthdatedetail = Object.entries(birthdatedetailByCategory).map(entry => {
        const [category, value] = entry;
        
        // Step through all entries to ensure we remove keys of your selection
        const categorydetail = value.map(d => {
          delete d.birthdate;
          delete d.category;
          return d;
        });
        
        return { category, categorydetail };
      });
      
      return { birthdate, birthdatedetail };
    });
    
    console.log(transformedData);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

    【讨论】:

      【解决方案3】:

      这是用 lodash 对数组进行分组的函数:

      const formatedResponse = _(arr)
        .groupBy("birthdate")
        .map((items, birthdate) => {
          const birthdateDetails = _(items)
            .groupBy("category")
            .map((items, category) => {
              return {
                category,
                categoryDetails: items.map(({ day, name }) => ({ day, name }))
              };
            })
            .value();
      
          return {
            birthdate,
            birthdateDetails
          };
        })
        .value();
      

      【讨论】:

        【解决方案4】:

        可能是这样的

        const data = [
          { birthdate: "1993", day: "12", category: "a", name: "Ben" },
          { birthdate: "1993", day: "13", category: "a", name: "John" },
          { birthdate: "1993", day: "14", category: "b", name: "Larry" },
          { birthdate: "1994", day: "15", category: "", name: "Nicole" },        
        ];
        
        
        const group = (data) => {
          return _(data)
            .groupBy('birthdate')
            .map((birthdateItems, birthdate) => ({
                birthdate,
                birthdateDetail: _(birthdateItems)
                  .groupBy('category')
                  .map((catgoryItems, category) => ({
                      category,
                      categoryDetail: _(catgoryItems)
                          .map(item => _.omit(item, ['birthdate', 'category']))
                          .value()
                  }))
                  .value()
            }))
            .value();
        }
        
        console.log(group(data));
        <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

        【讨论】:

          猜你喜欢
          • 2021-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-11
          相关资源
          最近更新 更多