【问题标题】:javascript sort by nearest start date time to present to furthest away and another attributejavascript按最近的开始日期时间排序以呈现最远和另一个属性
【发布时间】:2019-04-09 21:27:25
【问题描述】:

我必须按照开始日期时间进行排序,并参考具有多个属性的当前日期时间。 例如,我有这个列表:

<ul>
    <li data-startDate="09-04-2019 15:00" data-inplay=false>Name1</li>
    <li data-startDate="09-04-2019 15:30" data-inplay=false>Name2</li>
    <li data-startDate="09-04-2019 15:20" data-inplay=false>Name3</li>
    <li data-startDate="09-04-2019 16:00" data-inplay=false>Name4</li>
    <li data-startDate="09-04-2019 15:00" data-inplay=true> Name5</li>
    <li data-startDate="09-04-2019 15:10" data-inplay=false>Name6</li>
    <li data-startDate="09-04-2019 15:05" data-inplay=true> Name7</li>
    <li data-startDate="08-04-2019 12:05" data-inplay=false>Name8</li>
</ul>

当前日期时间为 09-04-2019 15:15,所需输出应为:

<!--
  Let currentDate = 09-04-2019 15:15
  Sort priority:
    1. inplay is true
    2. startDate is greater than currentDate
    3. startDate is lesser than currentDate
-->
<ul>
  <!-- inplay == true -->
  <li data-startDate="09-04-2019 15:05" data-inplay=true>Name7</li>
  <li data-startDate="09-04-2019 15:00" data-inplay=true>Name5</li>

  <!-- startDate > currentDate -->
  <li data-startDate="09-04-2019 15:20" data-inplay=false>Name3</li>
  <li data-startDate="09-04-2019 15:30" data-inplay=false>Name2</li>
  <li data-startDate="09-04-2019 16:00" data-inplay=false>Name4</li>

  <!-- startDate < currentDate -->
  <li data-startDate="09-04-2019 15:10" data-inplay=false>Name6</li>
  <li data-startDate="09-04-2019 15:00" data-inplay=false>Name1</li>
  <li data-startDate="08-04-2019 12:05" data-inplay=false>Name8</li>
</ul>

我试过了,但不包括 inplay 参数,而且顺序也不完全正确

var list = $("ul > li");
var target = new Date().getTime();
var sortByStartTime = function (a, b) {
    var ret = 0;
    var startDateA = $(a).data("startdate");
    var startDateB = $(b).data("startdate");
    var dateA = startDateA.split(" ")[0].split("-");
    var timeA = startDateA.split(" ")[1].split(":");
    var dateB = startDateB.split(" ")[0].split("-");
    var timeB = startDateB.split(" ")[1].split(":");
    startDateA = new Date(dateA[2], dateA[1] - 1, dateA[0], timeA[0], timeA[1]);
    startDateB = new Date(dateB[2], dateB[1] - 1, dateB[0], timeB[0], timeB[1]);
    var dA = Math.abs(startDateA.getTime() - target);
    var dB = Math.abs(startDateB.getTime() - target);
    if (dA < dB) {
        ret = -1;
    } else if (dA > dB) {
        ret = 1;
    }  else {
        ret = 0;
    }
    return ret;
};

list.sort(sortByStartTime);

for (var i = 0; i < list.length; i = i + 1) {
    list[i].parentNode.appendChild(list[i]);
}

基本上,列表应按最近的开始日期时间(相对于当前日期时间)排序到最远,但如果有一些 inplay,它们应该位于按最近的开始日期时间排序的列表顶部(相对于当前日期时间)到最远。我希望我解释得足够清楚。 任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 嗨@Bogdan - 你的要求或解释有点不准确。我看到按 inplay attr 排序并按 startdatetime 排序,但我看到 2 组 inplay 为 false 和一些随机排序的日期时间。你能解释一下吗?
  • 嗨 @user2648008 得到了有效的响应,感谢您的输入

标签: javascript sorting


【解决方案1】:

排序逻辑:

  1. 按数据inplay真假排序,使用数字简化排序逻辑(降序排序)
  2. 如果差异相反 零边先保持正值,后保持负值 (按降序排列)
  3. 如果与当前时间的差异 对于两个日期都在 0 的同一侧,按它们的绝对值排序 值(按升序排序)

var list = Array.from(document.querySelectorAll("ul > li"));
var target = new Date('09-04-2019 15:15');
var boolValue = { true: 1, false: 0 };
var sortByStartTime = function (a, b) {
    var diffA = new Date(a.dataset.startdate) - target;
    var diffB = new Date(b.dataset.startdate) - target;
    var inplayA = boolValue[a.dataset.inplay];
    var inplayB = boolValue[b.dataset.inplay];
    return inplayB - inplayA || (
        diffA < 0 === diffB < 0 ? Math.abs(diffA) - Math.abs(diffB) : diffB - diffA
    );
};

list.sort(sortByStartTime);

for (var i = 0; i < list.length; i = i + 1) {
    list[i].parentNode.appendChild(list[i]);
}
<ul>
  <li data-startDate="09-04-2019 15:00" data-inplay=false>Name1</li>
  <li data-startDate="09-04-2019 15:30" data-inplay=false>Name2</li>
  <li data-startDate="09-04-2019 15:20" data-inplay=false>Name3</li>
  <li data-startDate="09-04-2019 16:00" data-inplay=false>Name4</li>
  <li data-startDate="09-04-2019 15:00" data-inplay=true> Name5</li>
  <li data-startDate="09-04-2019 15:10" data-inplay=false>Name6</li>
  <li data-startDate="09-04-2019 15:05" data-inplay=true> Name7</li>
  <li data-startDate="08-04-2019 12:05" data-inplay=false>Name8</li>
</ul>

PS: 将new Date('09-04-2019 15:15'); 替换为new Date(); 以获得您想要的。我对日期进行了硬编码,以表明结果符合您的要求。

【讨论】:

  • 你的输出和想要的输出不一样
  • 感谢您的帮助。
【解决方案2】:

您可以使用 spread operator [...document.querySelectorAll('li')] 像数组一样获取 lis 元素

然后创建lisSorted,它将包含按元素属性data-startDate和布尔属性data-inplay排序的元素数组

代码:

const ul = document.querySelector('ul');
const lis = [...ul.querySelectorAll('li')];
const lisSorted = lis
  .sort((a, b) => {
    const x = a.getAttribute('data-inplay');
    const y = b.getAttribute('data-inplay');
    return ((x === y) ? 0 : x ? -1 : 1) || new Date(b.getAttribute('data-startDate')) - new Date(a.getAttribute('data-startDate'));
  });

ul.append(...lisSorted);
<ul>
  <li data-startDate="09-04-2019 15:00" data-inplay=false>Name1</li>
  <li data-startDate="09-04-2019 15:30" data-inplay=false>Name2</li>
  <li data-startDate="09-04-2019 15:20" data-inplay=false>Name3</li>
  <li data-startDate="09-04-2019 16:00" data-inplay=false>Name4</li>
  <li data-startDate="09-04-2019 15:00" data-inplay=true> Name5</li>
  <li data-startDate="09-04-2019 15:10" data-inplay=false>Name6</li>
  <li data-startDate="09-04-2019 15:05" data-inplay=true> Name7</li>
  <li data-startDate="08-04-2019 12:05" data-inplay=false>Name8</li>
</ul>

【讨论】:

  • 这不考虑data-inplay 属性。如果为真,它们应该排在所有其他结果之前。
  • @Mathyn 谢谢你的评论.. 更新答案
猜你喜欢
  • 1970-01-01
  • 2019-08-16
  • 2016-01-31
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多