使用 lodash 进行多级分组和填充数组

Multi level grouping and populate arrays with using lodash

我在看下面的例子

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

    [
      { 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" }],
  },
];

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

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

因为 _.groupBy returns an object, we will need to use 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>

这是用 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();

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

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

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; }

可能是这样的

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>