【问题标题】:javascript question about sorting array with timestamps关于使用时间戳对数组进行排序的 javascript 问题
【发布时间】:2021-02-21 14:18:17
【问题描述】:

我不太熟悉在 Javascript 中对数组和对象进行排序,我想知道在某些条件下如何对对象进行排序。 最终目标是在日历函数中使用这种排序。

举个例子,假设我们有类似下面的 sn-p 的情况:

$(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>

让我们不再关注如何将数据放入数组或对象中,而是关注将数据排序为正确顺序/格式的过程。

event id date time start time end minutes
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 以用于样式设置。

也就是说一旦元素定位完成,原始数据按照上面的数据,我需要按照以下条件对数据进行排序:

  1. 最早的开始日期为first。
  2. 如果 2 个元素具有相同的开始日期,则持续时间较长的元素优先于另一个元素

按照这个逻辑,上面的结果应该按照以下顺序结束

event id date time start time end minutes
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

我已经用一个工作示例更新了 sn-p,但如果有更好的方法来完成同样的事情,请告诉我。

/C

【问题讨论】:

  • 向我们展示您的尝试。 SO 不是免费的代码编写服务。此处的目的是让您发布解决自己问题的尝试,并在其他人无法按预期工作时提供帮助。见How to Askminimal reproducible example
  • 明白了!我会在睡觉后发布我的尝试!
  • 我已经用代码的工作副本更新了我的 sn-p,但仍然想知道是否有更好的方法来编写代码。非常感谢任何反馈。
  • 如果您的比较器在“diff”值相同时没有返回一致的结果,您的排序将产生不可预知的结果。如果多次比较数组中的两个元素,则无法保证它们会以相同的顺序进行比较。
  • 另外,如果“diff”值是一个数字,你可以直接返回b.diff - a.diff,这样就可以解决问题了。

标签: javascript arrays sorting jquery-multisortable


【解决方案1】:

您可以像使用 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) &gt; 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;

【讨论】:

  • 感谢您的建议,稍后再试一试!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 2014-01-03
  • 1970-01-01
相关资源
最近更新 更多