【问题标题】:Replace object in array with two objects用两个对象替换数组中的对象
【发布时间】:2018-10-03 15:13:05
【问题描述】:

我有一个包含结束日期和开始日期的对象数组。但日期之间的时间段可能跨越午夜。如果他们这样做,我希望用两个对象替换该对象,第一个是前一个开始日期,一个是午夜结束日期。第二个开始时间是第二天 00:00,结束日期是之前的时间。

例如,如果数组包含这样的对象,

{
  "start": "2016-11-04 22:00",
  "end": "2016-11-05 03:00"
}

我想用两个对象替换那个对象,

{
  "start": "2016-11-04 22:00",
  "end": "2016-11-04 24:00"
},
{
  "start": "2016-11-05 00:00",
  "end": "2016-11-05 03:00"
}

这是我使用data.push() 的尝试。显然这不是这样做的方法:

d3.json("data.json", function(data) {
  var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
  data.forEach(function(d) {
    d.commence = parseTime(d.start);
    d.conclude = parseTime(d.end);
    if (d.commence.getDay() != d.conclude.getDay()) {
      midnight = d.commence.getFullYear() + "-" + d.commence.getMonth() + "-" + d.commence.getDay() + " 24:00";
      morning = d.conclude.getFullYear() + "-" + d.conclude.getMonth() + "-" + d.conclude.getDay() + " 00:00";
      data.push({
        "start": d.start,
        "end": midnight
      }, {
        "start": morning,
        "end": d.end
      })
    }
  });
...

那么当我遍历对象数组时,如何添加或删除对象呢?

数据是这样开始的,

[
  {
    "start": "2016-11-01 12:00",
    "end": "2016-11-01 22:00"
  },
  {
    "start": "2016-11-02 02:00",
    "end": "2016-11-02 18:00"
  },
  {
    "start": "2016-11-03 09:00",
    "end": "2016-11-03 12:00"
  },
  {
    "start": "2016-11-04 22:00",
    "end": "2016-11-05 03:00"
  },
  {
    "start": "2016-11-06 12:00",
    "end": "2016-11-06 23:00"
  }
]

在控制台中我可以看到它最终看起来像这样,

[
  {
    "start": "2016-11-01 12:00",
    "end": "2016-11-01 22:00",
    "commence": "2016-11-01T12:00:00.000Z",
    "conclude": "2016-11-01T22:00:00.000Z"
  },
  {
    "start": "2016-11-02 02:00",
    "end": "2016-11-02 18:00",
    "commence": "2016-11-02T02:00:00.000Z",
    "conclude": "2016-11-02T18:00:00.000Z"
  },
  {
    "start": "2016-11-03 09:00",
    "end": "2016-11-03 12:00",
    "commence": "2016-11-03T09:00:00.000Z",
    "conclude": "2016-11-03T12:00:00.000Z"
  },
  {
    "start": "2016-11-04 22:00",
    "end": "2016-11-05 03:00",
    "commence": "2016-11-04T22:00:00.000Z",
    "conclude": "2016-11-05T03:00:00.000Z"
  },
  {
    "start": "2016-11-06 12:00",
    "end": "2016-11-06 23:00",
    "commence": "2016-11-06T12:00:00.000Z",
    "conclude": "2016-11-06T23:00:00.000Z"
  },
  {
    "start": "2016-11-04 22:00",
    "end": "2016-10-5 24:00"
  },
  {
    "start": "2016-10-6 00:00",
    "end": "2016-11-05 03:00"
  }
]

完整代码在github 上,演示在gh-pages 上运行。

任何建议将不胜感激,

谢谢

【问题讨论】:

    标签: arrays object d3.js replace


    【解决方案1】:

    这是使用flatMap 概念(函数式编程)的解决方案:

    Array.prototype.flatMap = function(lambda) { 
      return Array.prototype.concat.apply([], this.map(lambda)); 
    };
    
    d3.json("data.json", function(data) {
    
      var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
      var formatEndOfDay = d3.timeFormat("%Y-%m-%d 24:00");
      var formatStartOfDay = d3.timeFormat("%Y-%m-%d %H:%M");
    
      var result = data.flatMap( d => {
        var start = parseTime(d.start);
        var end = parseTime(d.end);
        if (start.getDay() == end.getDay())
          return [d];
        else {
          var firstPart = { "start": d.start, "end": formatEndOfDay(start) }
          var secondPart = { "start": formatStartOfDay(end.setHours(0)), "end": d.end }
          return [firstPart, secondPart];
        }
      });
    
      console.log(result);
    });
    

    Array.prototype.flatMap = function(lambda) { 
      return Array.prototype.concat.apply([], this.map(lambda)); 
    };
    
    var data = [
      {
        "start": "2016-11-01 12:00",
        "end": "2016-11-01 22:00"
      },
      {
        "start": "2016-11-02 02:00",
        "end": "2016-11-02 18:00"
      },
      {
        "start": "2016-11-03 09:00",
        "end": "2016-11-03 12:00"
      },
      {
        "start": "2016-11-04 22:00",
        "end": "2016-11-05 03:00"
      },
      {
        "start": "2016-11-06 12:00",
        "end": "2016-11-06 23:00"
      }
    ];
    
    var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
    var formatEndOfDay = d3.timeFormat("%Y-%m-%d 24:00");
    var formatStartOfDay = d3.timeFormat("%Y-%m-%d %H:%M");
    
    var result = data.flatMap( d => {
      var start = parseTime(d.start);
      var end = parseTime(d.end);
      if (start.getDay() == end.getDay())
        return [d];
      else {
        var firstPart = { "start": d.start, "end": formatEndOfDay(start) }
        var secondPart = { "start": formatStartOfDay(end.setHours(0)), "end": d.end }
        return [firstPart, secondPart];
      }
    });
    
    console.log(result);
    <script src="https://d3js.org/d3.v4.min.js"></script>

    提醒一下,这里有一个flatMap的例子:列表的每个元素都转化为多个元素;然后将这些子列表展平以生成一个列表:

    Array.prototype.flatMap = function(lambda) { 
      return Array.prototype.concat.apply([], this.map(lambda)); 
    };
    
    console.log([1, 2, 3, 4].flatMap(d => d % 2 == 0 ? [d, d] : [d]))

    在我们的例子中,这意味着遍历每个开始/结束元素,如果一个元素的开始和结束在同一天,那么我们将其转换为一个包含 1 个元素(本身)的列表;如果一个元素不是在同一天开始和结束,那么我们将它转​​换为一个包含 2 个元素的列表(第一天/结束日)。


    由于 javascript 没有内置的 flatMap 实现,我们可以这样创建一个:

    Array.prototype.flatMap = function(lambda) { 
      return Array.prototype.concat.apply([], this.map(lambda)); 
    };
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 2015-03-31
    相关资源
    最近更新 更多