Заменить объект в массиве двумя объектами

У меня есть массив объектов, которые содержат дату окончания и дату начала. Но промежуток между свиданиями может колебаться между полуночью. Если они это сделают, я хочу заменить объект двумя объектами, первый с предыдущей датой начала и датой окончания в полночь. Второй со временем начала 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-страницы.

Любые предложения будут ценны,

Спасибо

Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
0
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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.info(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.info(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.info([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)); 
};

Что ж, это сложный ответ, может быть, намного больше, чем нужно. Мне нужно будет прочитать о лямбда-функциях. Спасибо, что посмотрели на это. Я получил его почти работать в github.com/shanegibney/D3-Date-Hours-Graph, но у меня возникла новая проблема, о которой я писал здесь stackoverflow.com/questions/49989105/… Спасибо за вашу помощь, очень признателен

Shane G 23.04.2018 22:08

Другие вопросы по теме