Internet排序比较功能在Internet Explorer中失败

时间:2017-03-29 20:56:22

标签: javascript sorting date

我有一个基于枢轴命令日期的功能。请注意,此函数忽略提供日期的年份。例如,如果截止日期为1月7日,则所有日期将从7月1日到3月31日订购。问题似乎在于我的排序比较功能,它在Chrome和Firefox中完美运行,但在IE中却失败了。生成的statsDataPoints(Array)不会被排序。

这就是日期数组的样子:

[{"Min":"6.0", "Mean":"10.8", "Max":"32.1", "StdDev":"7.5", "LowerPercentile":"6.7", "Median":"8.0", "UpperPercentile":"11.2", "_Name":"30-Mar"}, {"Min":"6.0", "Mean":"11.1", "Max":"31.7", "StdDev":"7.4", "LowerPercentile":"7.3", "Median":"8.7", "UpperPercentile":"11.1", "_Name":"31-Mar"}, {"Min":"6.0", "Mean":"10.9", "Max":"31.4", "StdDev":"7.3", "LowerPercentile":"7.2", "Median":"8.4", "UpperPercentile":"11.0", "_Name":" 1-Apr"}, ... ]

这是我的功能:

/**
 * Returns a function which orders dates based on a pivot. Note that this function ignores the year of the
 * supplied dates. It is easiest to illustrate how this function works with an example:
 * Given a pivot date of 1-July, all dates will be ordered from 1-July to 31-June. 
 *
 * @param {Array}  dates 	  An array of objects containing a date key.
 * @param {String} pivot 	  The pivot date we are sorting from (should be in the same format as dateKey)
 */

var dummyYear = 2000;
var pivot = moment(readingStartDate).format("DD-MMM");
pivot = moment(pivot, "DD-MMM").year(dummyYear);

statsDataPoints.sort(function(aDate, bDate) {

	var a = moment(aDate["_Name"], "DD-MMM").year(dummyYear).toDate();
	var b = moment(bDate["_Name"], "DD-MMM").year(dummyYear).toDate();

	if (((a < pivot) && (pivot < b)) || (a > b)) {
		return 1;
	} else if (((b < pivot) && (pivot < a)) || (a < b)) {
		return -1;
	}
	return 0;

});

3 个答案:

答案 0 :(得分:0)

您的比较函数为inconsistent:假设x=1y=3pivot=2您获得compare(x, y) == 1,但compare(y, x) == 1因为{|| 1}}在第一个条件下。

我怀疑你打算使用

if ((a < pivot) && (pivot < b))
    return 1;
if ((b < pivot) && (pivot < a))
    return -1;
if (a > b) {
    return 1;
if (a < b)
    return -1;
return 0;

答案 1 :(得分:0)

感谢@CBroe,@ yBrodsky和@Bergi的回复。我设法通过简化我的代码来解决这个问题,而不是使用排序,这很不幸,但是IE并没有真正处理排序比较功能。

鉴于我的数据系列顺序正确,我只是简单地将数据点移到数组的末尾,以确保我的系列在当前日期开始。

为了澄清这一点,我就是这样做的:

&#13;
&#13;
// shift series by number of days since start of the year
var startOfYeat = moment().startOf('year');
var curDate = moment();
var daysSinceStartOfYear = curDate.diff(startOfYeat, 'days');

for (i = 0; i < daysSinceStartOfYear; i++) {
    statsDataPoints.push(statsDataPoints.shift());
}
&#13;
&#13;
&#13;

令人遗憾的是IE似乎并不支持简单的比较功能,所以如果有人对IE中的排序失败有其他想法,请在此处留言。

答案 2 :(得分:0)

问题是您的排序算法对日期传递给它的顺序很敏感。 IE使用不同的排序算法,因此以不同的顺序获取源数据到Firefox,因此有时您会得到不同的结果,有时您不会,这取决于原始数组中日期的顺序。

所以不是IE的错,你应该感谢它有助于识别算法的问题。 ; - )

您的代码中还存在其他一些缺陷。如果您按照moment.js提供的错误消息,您将看到以下行:

var pivot = moment(readingStartDate).format("DD-MMM");

发出警告:

  

弃用警告:提供的值不在公认的RFC2822或   ISO格式。时刻构造回落到js Date(),这不是   所有浏览器和版本都可靠。非RFC2822 / ISO日期   不鼓励格式,将在即将到来的专业中删除   发布。请参阅   http://momentjs.com/guides/#/warnings/js-date/了解更多信息。   参数:[0] _isAMomentObject:true,_isUTC:false,_useUTC:false,   _l:undefined,_ i:31-Mar,_f:undefined,_strict:undefined,_locale:[object Object] undefined

将该行更改为:

var pivot = moment(readingStartDate,'DD-MM').format('DD-MMM');

删除警告。另外,在行中:

(a < pivot) && (pivot < b)

您正在将时刻对象( pivot )与Date对象( a b )进行比较。最简单的解决方法是,如果 pivot 也是日期,那么:

var pivot = moment(readingStartDate,'DD-MM').format('DD-MMM').toDate();

您可以在IE 7中运行以下内容,但不幸的是,SO片段甚至不支持IE 10,因此您必须在别处运行它来测试IE。它虽然在Firefox 38中运行。

它表明以不同的顺序传递相同的值会产生不同的结果。

&#13;
&#13;
var statsDataPoints1 = [{"_Name": "30-Mar"}, {"_Name": " 1-Apr"}, {"_Name": "31-Mar"}];
var statsDataPoints2 = [{"_Name": "30-Mar"}, {"_Name": "31-Mar"}, {"_Name": " 1-Apr"}];

var readingStartDate = "31-Mar";
var dummyYear = 2000;
var pivot = moment(readingStartDate, 'DD-MM').format("DD-MMM");
pivot = moment(pivot, "DD-MMM").year(dummyYear).toDate();

function doStuff(statsDataPoints) {
  statsDataPoints.sort(function(aDate, bDate) {

    var a = moment(aDate["_Name"], "DD-MMM").year(dummyYear).toDate();
    var b = moment(bDate["_Name"], "DD-MMM").year(dummyYear).toDate();

    if (((a < pivot) && (pivot < b)) || (a > b)) {
      return 1;
    } else if (((b < pivot) && (pivot < a)) || (a < b)) {
      return -1;
    }
    return 0;
  });
}
   
// This source data sequence gives different results in Firefox and IE
doStuff(statsDataPoints1); 
for (var i = 0, iLen = statsDataPoints1.length; i < iLen; i++) {
  console.log(statsDataPoints1[i]._Name);
};

// Same data values as statsDataPoints1, different sequence
// Result has the same order in Firefox and IE
doStuff(statsDataPoints2); 
for (var i = 0, iLen = statsDataPoints2.length; i < iLen; i++) {
  console.log(statsDataPoints2[i]._Name);
};
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js"></script>
&#13;
&#13;
&#13;