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



Вот решение, использующее концепцию 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/… Спасибо за вашу помощь, очень признателен