javascript - 关于使用时间戳对数组进行排序的 javascript 问题
问题描述
我不太熟悉在 Javascript 中对数组和对象进行排序,并且想知道在某些条件下如何对对象进行排序。最终目标是在日历功能中使用这种排序。
举个例子,假设我们有一个类似下面代码片段的情况:
$(document).on('mouseup', '.event', function(){
var box_date = $(this).attr('date');
var param = [];
$(`.day[date=${box_date}] .event`).each(function(){
var box = $(this);
var row = {};
var time_start = box.attr('time_start');
var time_end = box.attr('time_end');
var id_event = box.attr('id_event');
var time_diff = timeDiff(time_start, time_end);
row.time_start = time_start;
row.time_end = time_end;
row.diff = time_diff;
row.id_event = id_event;
param.push(row);
})
console.log(param);
param.sort((a, b) => {
if (a.time_start < b.time_start){
return -1;
} else if (a.time_start > b.time_start){
return 1;
} else if (b.diff - a.diff) return -1;
return 1;
});
console.log(param);
})
function timeDiff(time_start, time_end){
var today = new Date(),
month = today.getMonth() + 1,
day = today.getDate(),
year = today.getFullYear();
month = month.toString();
month = month.padStart(2,'0');
day = day.toString();
day = day.padStart(2, '0');
date = [year, month, day].join('-');
var date1 = `${date} ${time_start}`;
var date2 = `${date} ${time_end}`;
date1 = new Date(date1);
date2 = new Date(date2);
var diff_time = Math.abs(date1 - date2);
// convert the time diff from ms to min
diff_time = diff_time / (1000 * 60);
return diff_time;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="day" date="2021-02-21">
<div class="event" id_event="1" date="2021-02-21" time_start="10:00" time_end="10:30">Val1</div>
<div class="event" id_event="2" date="2021-02-21" time_start="10:00" time_end="11:00">Val2</div>
<div class="event" id_event="3" date="2021-02-21" time_start="10:00" time_end="12:00">Val3</div>
<div class="event" id_event="4" date="2021-02-21" time_start="09:30" time_end="12:00">Val4</div>
<div class="event" id_event="5" date="2021-02-21" time_start="13:00" time_end="15:00">Val5</div>
</div>
让我们不要关注如何将数据放入数组或对象中,而是关注将数据排序为正确顺序/格式的过程。
事件编号 | 日期 | 时间开始 | 时间结束 | 分钟 |
---|---|---|---|---|
1 | 2021-02-21 | 10:00 | 10:30 | 30 |
2 | 2021-02-21 | 10:00 | 11:00 | 60 |
3 | 2021-02-21 | 10:00 | 12:00 | 120 |
4 | 2021-02-21 | 09:30 | 12:00 | 150 |
5 | 2021-02-21 | 13:00 | 15:00 | 120 |
获取数据时,它们按上述顺序显示,但由于用户可以移动和扩展/缩小每个元素,因此我需要相应地设置事件 div 的 z-index 以进行样式设置。
这意味着一旦元素的定位完成并且原始数据根据上面的数据,我需要根据以下条件对数据进行排序:
- 最早的开始日期为第一个。
- 如果 2 个元素具有相同的开始日期,则持续时间较长的元素优先于另一个元素
通过遵循该逻辑,上述结果应遵循以下顺序
事件编号 | 日期 | 时间开始 | 时间结束 | 分钟 |
---|---|---|---|---|
4 | 2021-02-21 | 09:30 | 12:00 | 150 |
3 | 2021-02-21 | 10:00 | 12:00 | 120 |
2 | 2021-02-21 | 10:00 | 11:00 | 60 |
1 | 2021-02-21 | 10:00 | 10:30 | 30 |
5 | 2021-02-21 | 13:00 | 15:00 | 120 |
我已经用一个工作示例更新了片段,但如果有更好的方法来完成同样的事情,请告诉我。
/C
解决方案
您可以执行与使用 SQL 相同的操作。
FROM events
ORDER BY time_start ASC, time_end DESC
在 JavaScript 中,这可以通过以下方式完成:
events.sort((a, b) => {
// time_start ascending
if (a.time_start < b.time_start) return -1;
if (a.time_start > b.time_start) return 1;
// time_end descending
if (a.time_end < b.time_end) return 1;
if (a.time_end > b.time_end) return -1;
// equal
return 0;
});
请注意,这是基于字符比较的,因为您的时间是零填充的,并且是 24 小时制。4:20
这在应该是的时间内失败了04:20
。如果没有0
前面,它将被认为比例如因为(第一个字符)晚。12:42
4 (code 0x34) > 1 (code 0x31)
我还添加了一个更具描述性的选项,但这确实引入了一些辅助函数。
$(document).on('mouseup', '.event', function(){
var box_date = $(this).attr('date');
var param = [];
$(`.day[date=${box_date}] .event`).each(function(){
var box = $(this);
var row = {};
var time_start = box.attr('time_start');
var time_end = box.attr('time_end');
var id_event = box.attr('id_event');
row.time_start = time_start;
row.time_end = time_end;
row.id_event = id_event;
param.push(row);
})
console.log(param);
param.sort((a, b) => {
// time_start ascending
if (a.time_start < b.time_start) return -1;
if (a.time_start > b.time_start) return 1;
// time_end descending
if (a.time_end < b.time_end) return 1;
if (a.time_end > b.time_end) return -1;
// equal
return 0;
});
console.log(param);
// or if you don't mind introducing some helpers
param.sort(asc(event => event.time_start).chain(desc(event => event.time_end)));
console.log(param);
})
// helpers
function asc(mapFn) {
return attachComparatorMethods(function (a, b) {
a = mapFn(a);
b = mapFn(b);
return -(a < b) || +(a > b);
});
}
function desc(mapFn) {
const comparator = asc(mapFn);
return attachComparatorMethods(function (a, b) {
return comparator(b, a);
});
}
function attachComparatorMethods(comparator) {
return Object.assign(comparator, {
chain(comparator) {
return attachComparatorMethods((a, b) => this(a, b) || comparator(a, b));
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="day" date="2021-02-21">
<div class="event" id_event="1" date="2021-02-21" time_start="10:00" time_end="10:30">Val1</div>
<div class="event" id_event="2" date="2021-02-21" time_start="10:00" time_end="11:00">Val2</div>
<div class="event" id_event="3" date="2021-02-21" time_start="10:00" time_end="12:00">Val3</div>
<div class="event" id_event="4" date="2021-02-21" time_start="09:30" time_end="12:00">Val4</div>
<div class="event" id_event="5" date="2021-02-21" time_start="13:00" time_end="15:00">Val5</div>
</div>
如果您在理解asc
帮助程序时遇到问题,可能是由于以下行:
return -(a < b) || +(a > b);
也可以写成:
if (a < b) return -1;
if (a > b) return 1;
return 0;
推荐阅读
- c# - C#订阅和取消订阅事件 - 从“字符串”
- html - 为什么我的自定义字体不显示(HTML、CSS、BEGINNER)
- javascript - 在 Puppeteer 中进行 Web Scraping 时如何处理验证码?
- spring - 如何修复 ModelAttributes 返回空值?
- quarkus - quarkus-maven-plugin 是否支持多模块项目?
- python - 使用 python 从 arduino 读取 usb 信号时出现极大噪音
- python - 为什么 allshortestpath 这么慢?
- python - 如果Kafka中不存在主题,如何使用kafka-python动态创建主题
- python - 从 Plotly 图表中删除 23:00
- sql - 统计表中的记录并显示特定值的行号