【问题标题】:Unable to get the desired result array无法得到想要的结果数组
【发布时间】:2016-08-09 15:55:02
【问题描述】:

我目前正在学习 lodash 和 moment.js,我正在使用一些虚拟数据。包含 1000 名医生列表的虚拟数据。我已经开始使用 Array.prototype.map()Array.prototype.filter() 并将很快将它们转换为 lodash。

数据

var doctors = [
  {
    "id": 0,
    "dateOfEmployment": "2012-12-27",
    "dateOfTermination": "2015-01-13",
    "dateOfBirth": "1978-06-06",
    "gender": "Male"
  },
  {
    "id": 1,
    "dateOfEmployment": "2016-02-08",
    "dateOfTermination": null,
    "dateOfBirth": "1984-04-21",
    "gender": "Female"
  },
  {
    "id": 2,
    "dateOfEmployment": "2010-11-30",
    "dateOfTermination": "2015-09-03",
    "dateOfBirth": "1975-09-24",
    "gender": "Male"
  },
  {
    "id": 3,
    "dateOfEmployment": "2012-06-17",
    "dateOfTermination": null,
    "dateOfBirth": "1980-08-31",
    "gender": "Female"
  },..];

我想获得过去 2 年的数组结果:

[{ date: '2015-04', count: 22 }, 
 { date: '2015-05', count: 25 },
 ...]

最初我尝试过这个:

    doctors = doctors.filter(function(doctor){
             return moment(doctor.dateOfEmployment).isBetween('2014-04', '2016-04');   
          }).map(function(doctor){
              return  {
            dates: moment(doctor.dateOfEmployment).format('YYYY-MM'),
            count: new Date(doctor.dateOfEmployment) - new Date(doctor.dateOfEmployment) + 1 };
      }););


console.log(doctors);

我很困惑。我是否应该首先使用 iddateOfEmploymentdateOfTermination 创建一个新的医生数组,然后记下这两个日期。然后过滤新的日期数组,条件是时刻为年份之间,然后映射/减少。

我确实想到了蛮力方法,我会在每个医生身上循环 24 次,并根据条件增加一个计数器,即 if doctorsEmployment 日期和 doctorsTermination 日期为 null 或等于临时日期。临时日期从 '2014-04' 到 '2016-04' 并最终将其推送到数组结果对象。

我是否以错误的方式处理这个问题?

任何帮助将不胜感激!

【问题讨论】:

  • 我觉得这更像是一个 reduce 操作,而不是 filter / map
  • 代替映射,试试这个:_.groupBy(filteredArray, doctor => moment(doctor.dateOfEmployment).format('YYYY-MM'))
  • 正如Phil 所说,您正在使用filter 创建一个数组,然后遍历该数组并使用map 创建另一个数组。使用 reduce 将允许您在一次迭代中完成这两项操作以创建一个数组。在调用函数之前将日期字符串转换为日期可能也更有效,否则您还会在每个循环上创建新的 Dates 或 moment.js 实例。
  • new Date(doctor.dateOfEmployment) - new Date(doctor.dateOfEmployment) 的结果将是 NaN 或零。

标签: javascript arrays momentjs


【解决方案1】:

不是 lodash 或 moment.js,但这里是如何在纯 JS 中做到这一点:

// Sample data
var doctors = [
  {
    "id": 0,
    "dateOfEmployment": "2012-12-27",
    "dateOfTermination": "2015-01-13",
    "dateOfBirth": "1978-06-06",
    "gender": "Male"
  },
  {
    "id": 1,
    "dateOfEmployment": "2016-02-08",
    "dateOfTermination": null,
    "dateOfBirth": "1984-04-21",
    "gender": "Female"
  },
  {
    "id": 2,
    "dateOfEmployment": "2016-02-29",
    "dateOfTermination": "2015-09-03",
    "dateOfBirth": "1975-09-24",
    "gender": "Male"
  },
  {
    "id": 3,
    "dateOfEmployment": "2015-06-17",
    "dateOfTermination": null,
    "dateOfBirth": "1980-08-31",
    "gender": "Female"
  }];
 
// Parse ISO date string (e.g. 2016-04-01) as local
function parseISODate(s) {
  var b = s.split(/\D/);
  return new Date(b[0], b[1]? b[1] - 1 : 0, b[2] || 1);
}

var startDate = parseISODate('2014-04'),
    endDate   = parseISODate('2016-04');

// Creates an object with months and counts
var resultObj = doctors.reduce(function(acc, cur) {
  var d = parseISODate(cur.dateOfEmployment);
  if (d >= startDate && d <= endDate) {
    var month = d.toISOString().slice(0,7);
    acc[month] = (acc[month] || 0) + 1;
  }
  return acc;
}, {});

// Creates an array with required objects from result object
var resultArr = Object.keys(resultObj).map(function(key) {
  return {date: key, count: resultObj[key]};
})
 
document.write(
  JSON.stringify(resultObj) + '<br>' + // {"2016-02":2,"2015-06":1}
  JSON.stringify(resultArr)  // [{"date":"2016-02","count":2},{"date":"2015-06","count":1}]
);

这假设您只需要计数大于零的月份。它遍历原始数据一次,然后遍历结果对象一次,尽管我看不出数组是比创建它的对象更理想的格式。

请注意,我将源数据编辑为在 2016 年 2 月有两个 dateOfEmployment 日期。

【讨论】:

    【解决方案2】:

    如何使用 lodash 的 reduce...像这样:

    var doctors = [{
      "id": 0,
      "dateOfEmployment": "2014-12-27",
      "dateOfTermination": "2015-01-13",
      "dateOfBirth": "1978-06-06",
      "gender": "Male"
    }, {
      "id": 1,
      "dateOfEmployment": "2016-02-08",
      "dateOfTermination": null,
      "dateOfBirth": "1984-04-21",
      "gender": "Female"
    }, {
      "id": 2,
      "dateOfEmployment": "2015-11-30",
      "dateOfTermination": "2015-09-03",
      "dateOfBirth": "1975-09-24",
      "gender": "Male"
    }, {
      "id": 3,
      "dateOfEmployment": "2012-06-17",
      "dateOfTermination": null,
      "dateOfBirth": "1980-08-31",
      "gender": "Female"
    }];
    
    doctors = _.reduce(doctors, function(memo, doctor) {
      if (moment(doctor.dateOfEmployment).isBetween('2014-04', '2016-04')) {
        memo.push({
          dates: moment(doctor.dateOfEmployment).format('YYYY-MM'),
          count: new Date(doctor.dateOfEmployment) - new Date(doctor.dateOfEmployment) + 1
        });
      }
      return memo;
    }, []);
    console.log(doctors);
    

    工作fiddle

    【讨论】:

    • 请注意,这不会核对同一个月的 dateOfEmployment 的计数,它会为每个 [{dates:'2016-02', count:1}, {dates:'2016-02': count: 1}] 而不是 [{dates:'2016-02', count:2}] 创建一个新对象。还有 dates 不是 date (小问题……)。 ;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2016-03-14
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多