1

所以我有这样的数据(简化版):

const itemList = [
{itemDetail: {date: '2020-12-30' , quantity: 5, productType: 'shirt'  }},
{itemDetail: {date: '2021-01-05' , quantity: 4, productType: 'trouser'  }},
{itemDetail: {date: '2020-12-30', quantity: 1, productType: 'shirt'  }},
{itemDetail: {date: '2021-01-05', quantity: 2, productType: 'jacket'}}
]

所需的输出:

const itemListFinalForm = [
{
   date: '2020-12-30',
   items: [{productType: 'shirt', quantity: 6}]
},
{
   date: '2021-01-05',
   items: [{productType: 'trouser', quantity: 4}, {productType: 'hat', quantity: 2}]
}
]

我已经尝试编写伪代码,但无法真正实现它。任何形式的答案将不胜感激。谢谢

4

5 回答 5

1

const itemList = [
  { itemDetail: { date: '2020-12-30', quantity: 5, productType: 'shirt' } },
  { itemDetail: { date: '2021-01-05', quantity: 4, productType: 'trouser' } },
  { itemDetail: { date: '2020-12-30', quantity: 1, productType: 'shirt' } },
  { itemDetail: { date: '2021-01-05', quantity: 2, productType: 'jacket' } },
  { itemDetail: { date: '2021-01-06', quantity: 3, productType: 'jacket' } },
]

const itemsByType = {};
const itemsByDate = {};

itemList.forEach(({ itemDetail }) => {
  const { productType, date, quantity } = itemDetail;
  if (itemsByType[productType]?.[date]) {
    itemsByType[productType][date] = itemsByType[productType][date] + quantity;
  } else {
    itemsByType[productType] = { [date]: quantity };
  }
});

Object.entries(itemsByType).forEach(([productType, info]) => {
  Object.entries(info).forEach(([date, quantity]) => {
    if (itemsByDate[date]) {
      itemsByDate[date].push({ quantity, productType });
    } else {
      itemsByDate[date] = [{ quantity, productType }];
    }
  });
});

const result = Object.entries(itemsByDate).map(([date, items]) => ({ date, items }));

console.log(result);

于 2021-01-14T13:09:58.923 回答
0

下面我做了一个简单的例子

const itemList = [{
    itemDetail: {
      date: '2020-12-30',
      quantity: 5,
      productType: 'shirt'
    }
  },
  {
    itemDetail: {
      date: '2021-01-05',
      quantity: 4,
      productType: 'trouser'
    }
  },
  {
    itemDetail: {
      date: '2020-12-30',
      quantity: 1,
      productType: 'shirt'
    }
  },
  {
    itemDetail: {
      date: '2021-01-05',
      quantity: 2,
      productType: 'jacket'
    }
  }
]


var data = itemList.reduce((acc, item) => {
  var d = acc.find(x => x.date == item.itemDetail.date);
  if (!d) {
    acc.push({
      date: item.itemDetail.date,
      items: [{
        quantity: item.itemDetail.quantity,
        productType: item.itemDetail.productType
      }]
    });
  } else {
    var type = d.items.find(x => x.productType == item.itemDetail.productType);
    if (!type) {
      d.items.push({
        quantity: item.itemDetail.quantity,
        productType: item.itemDetail.productType
      })
    } else type.quantity += item.itemDetail.quantity
  }
  return acc;
}, [])

console.log(data)

于 2021-01-14T13:11:56.593 回答
0

驱动到极致,您可以在“单行”中完成所有操作,请参见此处:

const itemList = [
{itemDetail: {date: '2020-12-30' , quantity: 5, productType: 'shirt'  }},
{itemDetail: {date: '2021-01-05' , quantity: 4, productType: 'trouser'  }},
{itemDetail: {date: '2020-12-30', quantity: 1, productType: 'shirt'  }},
{itemDetail: {date: '2021-01-05', quantity: 2, productType: 'jacket'}}
];

const res=Object.entries
(itemList.reduce
  ((a,{itemDetail},i)=>
     (i=a[itemDetail.date]=a[itemDetail.date]||{},
      i[itemDetail.productType]=+itemDetail.quantity+(i[itemDetail.productType]||0),
      a
     ), {} 
  )
).map(([k,o])=>({date: k, items: Object.entries(o).map(([p,n])=>({productType: p,quantity: n }) )}));

console.log(res)

于 2021-01-14T15:11:00.160 回答
0

首先,您必须通过分组来减少您的项目productType。接下来,您可以累积数量并找到最短日期。完成后,您可以按 分组date。然后,您可以将分组数据转换为最终结构。最后,您可以按date.

如果您考虑每个离散步骤,它会使整个算法易于遵循。

const itemList = [
  { itemDetail: { date: '2020-12-30', quantity: 5, productType: 'shirt' }},
  { itemDetail: { date: '2021-01-05', quantity: 4, productType: 'trouser' }},
  { itemDetail: { date: '2020-12-30', quantity: 1, productType: 'shirt' }},
  { itemDetail: { date: '2021-01-05', quantity: 2, productType: 'jacket' }}
];

const groupedByProductType = itemList.reduce((acc, item) => {
  const { itemDetail: { productType } } = item;
  const prev = acc[productType] || [];
  return { ...acc, [productType]: [ ...prev, item ] };
}, {});

const rollup = Object.entries(groupedByProductType).map(([productType, arr]) => {
  const minDate = Math.min(...arr.map(({ itemDetail: { date } }) => new Date(date)));
  const quantity = arr.reduce((acc, { itemDetail: { quantity } }) => acc + quantity, 0);
  const date = arr.find(({ itemDetail: { date } }) =>
    new Date(date).getTime() === minDate).itemDetail.date;
  return {
    itemDetail: {
      date,
      quantity,
      productType
    }
  };
});

const groupedByDate = rollup.reduce((acc, item) => {
  const { itemDetail: { date } } = item;
  const prev = acc[date] || [];
  return { ...acc, [date]: [ ...prev, item ] };
}, {});

const result = Object.entries(groupedByDate).map(([date, items]) => ({
  date,
  items: items.map(({ itemDetail: { productType, quantity } }) =>
    ({ productType, quantity }))
}));

result.sort(({ date: a }, { date: b }) => new Date(a) - new Date(b));

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

结果

[
  {
    "date": "2020-12-30",
    "items": [
      {
        "productType": "shirt",
        "quantity": 6
      }
    ]
  },
  {
    "date": "2021-01-05",
    "items": [
      {
        "productType": "trouser",
        "quantity": 4
      },
      {
        "productType": "jacket",
        "quantity": 2
      }
    ]
  }
]
于 2021-01-14T13:21:55.780 回答
0

此数据转换可分为 3 个(基本)步骤。

  1. 按日期对项目进行分组。
  2. 按日期对组进行排序。
  3. 将每个组转换为所需的结果。
    1. 按产品类型对日期组中的所有项目进行分组。
    2. 对每个产品类型组的数量求和。
    3. 将结果组合成所需的结果。

const itemList = [
  { itemDetail: { date: '2020-12-30', quantity: 5, productType: 'shirt'   } },
  { itemDetail: { date: '2021-01-05', quantity: 4, productType: 'trouser' } },
  { itemDetail: { date: '2020-12-30', quantity: 1, productType: 'shirt'   } },
  { itemDetail: { date: '2021-01-05', quantity: 2, productType: 'jacket'  } },
];

const itemListFinalForm =
  Array.from(groupBy(
    // map first since we don't need the itemDetail wrapper
    itemList.map(item => item.itemDetail),
    item => item.date,
  ))
  .sort(asc(([date]) => Date.parse(date)))
  .map(([date, items]) => ({
    date: date,
    items: Array.from(groupBy(items, item => item.productType))
      .map(([type, items]) => ({
        productType: type,
        quantity: sumBy(items, item => item.quantity),
      }))
  }));

console.log(itemListFinalForm);


// helpers
function groupBy(iterable, fn) {
  const groups = new Map();
  for (const item of iterable) {
    const key = fn(item);
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key).push(item);
  }
  return groups;
}

function asc(fn) {
  const cache = new Map();
  
  function fromCache(item) {
    if (!cache.has(item)) cache.set(item, fn(item));
    return cache.get(item);
  }
  
  return function (a, b) {
    a = fromCache(a);
    b = fromCache(b);
    return -(a < b) || +(a > b);
  }
}

function sumBy(iterable, fn) {
  let sum = 0;
  for (const item of iterable) sum += fn(item);
  return sum;
}

于 2021-01-14T14:06:33.537 回答