对包含字符串、日期和数字的数组进行排序

4
var myArray = [
    '_aaaa_2013-09-25_ssss9.txt',
    '_aaaa_2013-09-25_ssss8.txt',
    '_aaaa_2013-09-26_ssss1.txt',
    '_aaaa_2013-09-25_ssss10.txt',
    '_aaaa_2013-09-26_ssss2.txt',
    '_aaaa_2013-09-25_ssss13.txt',
    '_aaaa_2013-09-25_ssss5.txt',
    '_aaaa_2013-09-25_ssss6.txt',
    '_aaaa_2013-09-25_ssss7.txt'
];

我需要按照日期和数字对数组进行排序。
结果应该是:
var result = [
    '_aaaa_2013-09-25_ssss5.txt',
    '_aaaa_2013-09-25_ssss6.txt',
    '_aaaa_2013-09-25_ssss7.txt',
    '_aaaa_2013-09-25_ssss8.txt',
    '_aaaa_2013-09-25_ssss9.txt',
    '_aaaa_2013-09-25_ssss13.txt',
    '_aaaa_2013-09-26_ssss1.txt',
    '_aaaa_2013-09-26_ssss2.txt'
];

我尝试了以下代码。它可以按日期排序,但我需要按在“.txt”之前的数字进行排序。我应该怎么做?
myArray.sort(function (a, b) {

    var timeStamp1 = a.substring(a.indexOf('_aaaa') + 6, a.indexOf('_ssss'));
    var timeStamp2 = b.substring(b.indexOf('_aaaa') + 6, b.indexOf('_ssss'));
    timeStamp1 = new Date(Date.UTC(timeStamp1[0], timeStamp1[1], timeStamp1[2]));
    timeStamp2 = new Date(Date.UTC(timeStamp2[0], timeStamp2[1], timeStamp2[2]));

    return (timeStamp1 > timeStamp2) ? 1 : (timeStamp2 > timeStamp1 ? -1 : 0);

});

@sachin:您可以通过数字比较任何YMD日期。您甚至可以将YYYY-MM-DD日期作为字符串进行比较,但这在此处并不需要。而且,比较数字是微不足道的(如果您不知道,请搜索)。 - Bergi
我刚刚尝试了Ela发布的链接中被接受的解决方案,Bergi针对你的用例提出了建议,它可以按照你的要求进行排序。 - Arthur Weborg
@Bergi 我已经尝试过了,但是那并没有起作用。 - sachin
返回(timeStamp1 > timeStamp2)?1:0; - frenchie
1
永远不要因为没有得到答案就重复自己的问题。相反,编辑和改进您现有的问题。 - hakre
显示剩余3条评论
4个回答

1

这对我有用。

myArray.sort(function (a, b) {
    var a_s = a.substring(0, a.indexOf('ssss') + 4);
    var a_n = a.substring(a.indexOf('ssss') + 4, a.indexOf('.txt'));
    var b_s = b.substring(0, b.indexOf('ssss') + 4);
    var b_n = b.substring(b.indexOf('ssss') + 4, b.indexOf('.txt'));
    if (a_s < b_s)
        return -1;
    if (a_s > b_s)
        return 1;
    return parseInt(a_n) - parseInt(b_n);
});

jsFiddle

翻译为:

{{链接1:jsFiddle}}


我尝试了这个,但是没有得到精确的输出。首先我需要按日期排序,然后按在“.txt”之前的数字排序。现在它只按日期排序,没有按数字排序。 - sachin
请查看最后的 jsFiddle 链接。右下方的面板显示输出结果,按字符串然后数字排序,这与日期和数字排序相同(只要日期和月份左侧用“0”填充,例如“07”表示7月)。 - azz
请将您的答案移至http://stackoverflow.com/questions/19012468/javascript-sort-an-array-of-strings-that-can-contain-letters-numbers-and-dates。 - hakre
如果你认为这是一个很好的答案(值得采取行动),请将其移动到重复问题的重复问题。 - hakre

1
你可以这样做:

var re = /^_aaaa_(\d\d\d\d-\d\d-\d\d)_ssss(\d+)\.txt$/;

var result = myArray.slice().sort( function( a, b ) {
    var aa = a.match(re), bb = b.match(re);
    return(
        aa[1] < bb[1] ? -1 :
        aa[1] > bb[1] ? 1 :
        aa[2] - bb[2]
    );
});

请注意使用.slice()来创建数组的副本。如果您想在原地对原始数组进行排序,则可以省略此步骤。(感谢@DerFlatulator提醒!)

您好,我尝试了这个但是出现错误:aa[1] < bb[1] ? -1 : TypeError: 无法读取 null 的属性 '1'。 - sachin
1
这个错误的意思是正则表达式与数组元素中的文本不匹配。因此,你的数据似乎必须与你在问题中发布的内容不同。如果你将myArray的定义粘贴到Chrome控制台,然后再粘贴我的代码,result的值将是你要寻找的结果。你的数据或代码有什么不同? - Michael Geary
@DerFlatulator 我的数据是:cccc_aaaa_2013-09-26_ssss1.txt - sachin
请注意,此答案将修改myArray并将结果存储在result中。如果您想制作数组的浅拷贝,请使用类似于var result = myArray.slice().sort(...);的东西。另外,为什么我的标签出现在这个答案中? - azz

0

按字符串中的数字值进行排序。

假定:

  • 数字是整数
  • 每个字符串都不同
  • 日期可以按数字排序(年,月,日)

["aa_123","aa_13","aa_2","aa_22_bb_23","aa_22_bb_3"].sort( function ( a , b ) {

    var as = a.split(/([0-9]+)/); // splits string retaining separators
    var bs = b.split(/([0-9]+)/);
    var i,c = Math.min(as.length,bs.length);
    for ( i=0;i<c && as[i]===bs[i];++i ) ;
    var an = (i&1)?+as[i]:as[i]; // separators (digits) always at odd index
    var bn = (i&1)?+bs[i]:bs[i];
    return (an<bn)?-1:1; // assumes every string different

} );

结果:

[
  "aa_2",
  "aa_13",
  "aa_22_bb_3",
  "aa_22_bb_23",
  "aa_123"
]

0
该程序从给定的字符串中提取数字,并对每个数字部分施加给定的权重。这样,您可以按照数量、日、月、年的优先级以任意顺序进行排序。
function weightedNumSort(myArray,weightNum,weightString) {    
    var WEIGHTS_NUM = weightNum || [1,2,4,3]; //[YEAR,MONTH,DAY,COUNT], You can pass an array with appropriate weights for the number at the given position in the text, e.g year is the first Number
    var WEIGHT_STRING = weightString || 1; //And a weight for the string value. If none get passed, default weights are used

        function weightedSum (a,b,i) {
            return ( a  +  b * ( WEIGHTS_NUM [i-1] || 1 ));
        }

    myArray = myArray.slice().sort(function (a, b) {
        var reg = /(\d+)/g //A regex to extract the numerical part

        var lNum = a.match(reg) //Extract the numerical parts we now have an array ["2013","09","26","2"]

        var rNum = b.match(reg)

        var delta = Array.apply(null,{length:lNum.length+1});
            delta [0] = 0; //add a 0 at the beginning, for convenience with the reduce function

        for (var i=0,j=lNum.length; i < j; i++) {
            var value = lNum[i] - rNum[i];
            value = ~~ (value / Math.abs (value)) // 1 for positive values, 0 for 0 , -1 for negative values, to make weighting easier
            delta[i+1] = value;
        }

        var weightedNumValue = delta.reduce (weightedSum) //Put a weight on the number parts.
        var weightedStrValue = WEIGHT_STRING * ( a > b ? 1 : a < b ? -1 : 0 )    
        return weightedNumValue + weightedStrValue //Add the weighted values and we have a positive or negative value with a correct weight on the numerical parts
    })
    return  myArray
}

输出

console.log (
   weightedNumSort (myArray)    
) /*
[
  "_aaaa_2013-09-25_ssss5.txt",
  "_aaaa_2013-09-25_ssss6.txt",
  "_aaaa_2013-09-25_ssss7.txt",
  "_aaaa_2013-09-25_ssss8.txt",
  "_aaaa_2013-09-25_ssss9.txt",
  "_aaaa_2013-09-25_ssss10.txt",
  "_aaaa_2013-09-25_ssss13.txt",
  "_aaaa_2013-09-26_ssss1.txt",
  "_aaaa_2013-09-26_ssss2.txt"
]*/

还有一个Fiddle


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接