我正在尝试使用reduce实现一个功能,该功能允许我按周对对象数组{ date: '2019-03-11', count: 8 }进行分组。到目前为止,我可以按周对日期进行分组,但是如果日期在同一周,则我很难将count加在一起。

const dates = [
  { date: '2019-03-11', count: 8 },
  { date: '2019-03-12', count: 7 },
  { date: '2019-03-09', count: 6 },
  { date: '2019-02-27', count: 10 },
  { date: '2019-02-26', count: 11 },
  { date: '2019-02-22', count: 12 },
  { date: '2019-04-21', count: 3 },
  { date: '2019-04-18', count: 2 },
  { date: '2019-04-17', count: 4 },
  { date: '2019-04-19', count: 5 }
];
Date.prototype.getWeek = function() {
  const onejan = new Date(this.getFullYear(), 0, 1);
  return Math.ceil(((this - onejan) / 86400000 + onejan.getDay() + 1) / 7);
};

const groups = dates.reduce(function(acc, item) {
  const today = new Date(item.date);
  const weekNumber = today.getWeek(today);
  // check if the week number exists
  if (typeof acc[weekNumber] === 'undefined') {
    acc[weekNumber] = [];
  }

  acc[weekNumber].push(item.date, item.count);

  return acc;
}, {});

console.log(groups);


当前结果

javascript - 如何使用reduce JavaScript增加同一周的计数?-LMLPHP

所需结果

[
  { weekStart: '2019-02-17', count: 12 },
  { weekStart: '2019-02-24', count: 21 },
  { weekStart: '2019-03-03', count: 6 },
  { weekStart: '2019-03-10', count: 15 },
  { weekStart: '2019-04-14', count: 11 },
  { weekStart: '2019-04-21', count: 21 }
]


其中weekStart是分组的一周的第一个日期(星期日)



const dates = [
  { date: '2019-02-24', count: 10 },
  { date: '2019-02-25', count: 11 },
  { date: '2019-02-26', count: 12 },
  { date: '2019-03-09', count: 8 },
  { date: '2019-03-10', count: 7 },
  { date: '2019-03-11', count: 6 },
  { date: '2019-04-14', count: 3 },
  { date: '2019-04-15', count: 2 },
  { date: '2019-04-16', count: 4 },
  { date: '2019-04-22', count: 5 }
];

/**
 * Returns the week number for this date.  dowOffset is the day of week the week
 * "starts" on for your locale - it can be from 0 to 6. If dowOffset is 1 (Monday),
 * the week returned is the ISO 8601 week number.
 * @param int dowOffset
 * @return int
 */
Date.prototype.getWeek = function(dowOffset) {
  /*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.epoch-calendar.com */

  dowOffset = typeof dowOffset == 'int' ? dowOffset : 0; //default dowOffset to zero
  var newYear = new Date(this.getFullYear(), 0, 1);
  var day = newYear.getDay() - dowOffset; //the day of week the year begins on
  day = day >= 0 ? day : day + 7;
  var daynum =
    Math.floor(
      (this.getTime() -
        newYear.getTime() -
        (this.getTimezoneOffset() - newYear.getTimezoneOffset()) * 60000) /
        86400000
    ) + 1;
  var weeknum;
  //if the year starts before the middle of a week
  if (day < 4) {
    weeknum = Math.floor((daynum + day - 1) / 7) + 1;
    if (weeknum > 52) {
      nYear = new Date(this.getFullYear() + 1, 0, 1);
      nday = nYear.getDay() - dowOffset;
      nday = nday >= 0 ? nday : nday + 7;
      /*if the next year starts before the middle of
           the week, it is week #1 of that year*/
      weeknum = nday < 4 ? 1 : 53;
    }
  } else {
    weeknum = Math.floor((daynum + day - 1) / 7);
  }
  return weeknum;
};

function getWeekStart(date) {
  var offset = new Date(date).getDay();
  return new Date(new Date(date) - offset * 24 * 60 * 60 * 1000)
    .toISOString()
    .slice(0, 10);
}

function groupWeeks(dates) {
  const groupsByWeekNumber = dates.reduce(function(acc, item) {
    const today = new Date(item.date);
    const weekNumber = today.getWeek();

    // check if the week number exists
    if (typeof acc[weekNumber] === 'undefined') {
      acc[weekNumber] = [];
    }

    acc[weekNumber].push(item);

    return acc;
  }, []);

  return groupsByWeekNumber.map(function(group) {
    return {
      weekStart: getWeekStart(group[0].date),
      count: group.reduce(function(acc, item) {
        return acc + item.count;
      }, 0)
    };
  });
}

console.log(groupWeeks(dates));

最佳答案

您可以将工作日作为偏移量,然后从给定的日期中减去毫秒。

Reducing的工作原理是带有回调,并在键上加上星期几开始日期。

(m, { date, count }) =>                      // outer callback with map and object
    (k => m.set(k, (m.get(k) || 0) + count)) // closure over k and updating the count in map
    (getWeekStart(date))                     // get value for k




function getWeekStart(date) {
    var offset = new Date(date).getDay();
    return new Date(new Date(date) - offset * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
}

const
    dates = [{ date: '2019-03-11', count: 8 }, { date: '2019-03-12', count: 7 }, { date: '2019-03-09', count: 6 }, { date: '2019-02-27', count: 10 }, { date: '2019-02-26', count: 11 }, { date: '2019-02-22', count: 12 }, { date: '2019-04-21', count: 3 }, { date: '2019-04-18', count: 2 }, { date: '2019-04-17', count: 4 }, { date: '2019-04-19', count: 5 }],
    result = Array.from(
        dates.reduce((m, { date, count }) =>
            (k => m.set(k, (m.get(k) || 0) + count))(getWeekStart(date)),
            new Map),
        ([date, count]) => ({ date, count })
    );

console.log(result);

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

关于javascript - 如何使用reduce JavaScript增加同一周的计数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55808224/

10-12 01:01