我对我现在正在工作的项目有一个要求,这对我来说有点棘手。
基本上,我必须根据项的Text
属性对这些项的数组进行排序:
以下是我的项目:
var answers = [],
answer1 = { Id: 1, Text: '3-4 weeks ago' },
answer2 = { Id: 2, Text: '1-2 weeks ago' },
answer3 = { Id: 3, Text: '7-8 weeks ago' },
answer4 = { Id: 4, Text: '5-6 weeks ago' },
answer5 = { Id: 5, Text: '1-2 days ago' },
answer6 = { Id: 6, Text: 'More than 1 month ago' };
answers.push(answer1);
answers.push(answer2);
answers.push(answer3);
answers.push(answer4);
answers.push(answer5);
answers.push(answer6);
我需要分析每一项的Text
属性,以便在排序之后,数组看起来像这样:
answers[0] = { Id: 6, Text: 'More than 1 month ago' }
answers[1] = { Id: 3, Text: '7-8 weeks ago' }
answers[2] = { Id: 4, Text: '5-6 weeks ago' }
answers[3] = { Id: 1, Text: '3-4 weeks ago' }
answers[4] = { Id: 2, Text: '1-2 weeks ago' }
answers[5] = { Id: 5, Text: '1-2 days ago' }
逻辑是,日期离得越远,它的优先级就越高,因此它应该出现在数组中的第一位。因此,"1-2天“的优先级低于"7-8周”。
因此,逻辑是,我需要提取数字值,然后提取单位(例如天、周),并以某种方式根据这些详细信息对数组进行排序。
老实说,我发现很难想出一个解决方案,我很感激任何人的帮助。
编辑:考虑到我正在处理的数据,它是从web服务返回的,并且我没有能力更改文本。因此,我必须按原样使用它。
发布于 2012-11-23 01:00:12
您可以使用一个自定义排序函数来解析文本中的值,并按照here中描述的那样对它们进行数值比较。
var answers = [
{ Id: 1, Text: '3-4 weeks ago' },
{ Id: 2, Text: '1-2 weeks ago' },
{ Id: 3, Text: '7-8 weeks ago' },
{ Id: 4, Text: '5-6 weeks ago' },
{ Id: 5, Text: '1-2 days ago' },
{ Id: 6, Text: 'More than 1 month ago' }
];
answers.sort(function(a, b) {
function getVal(item) {
var val;
// find first number
var match = item.Text.match(/\d+/);
if (match) {
val = parseInt(match[0], 10);
} else {
val = 10000; // set to very high number
}
if (item.Text.indexOf("More than") !== -1) {
++val;
}
if (item.Text.indexOf("week") !== -1) {
val *= 7;
} else if (item.Text.indexOf("month") !== -1) {
val *= 30;
}
return(val);
}
return(getVal(b) - getVal(a));
});
工作演示:http://jsfiddle.net/jfriend00/cf3D7/
显然,您可以对getVal()
函数进行微调,以支持您想要的任何解析逻辑。
如果您的数组很大,您可以通过预先计算排序索引并将其存储在每个对象中来提高它的性能,以便自定义排序函数只直接比较两个数字,而不是每次都重新计算它。但是,数组少于100个项可能是无关紧要的。
此外,您还不清楚如何对“1个多月前”和"7-8周“进行排序。我目前的算法将“超过1个月前”视为1个月,但如果您有特定的规则,您可以调整解析逻辑。一旦拥有了自定义排序函数,排序逻辑的关键就在于getVal()
函数的实现,您可以调整该函数以支持您想要支持的任何语法。
这是一个预先计算sortKey的版本,因此在大型数组中执行得更好:
(function() {
function getVal(item) {
var val;
// find first number
var match = item.Text.match(/\d+/);
if (match) {
val = parseInt(match[0], 10);
} else {
val = 10000; // set to very high number
}
if (item.Text.indexOf("More than") !== -1) {
++val;
}
if (item.Text.indexOf("week") !== -1) {
val *= 7;
} else if (item.Text.indexOf("month") !== -1) {
val *= 30;
}
return(val);
}
for (var i = 0, len = answers.length; i < len; i++) {
answers[i].sortKey = getVal(answers[i]);
}
answers.sort(function(a, b) {
return(b.sortKey - a.sortKey);
});
})()
附注:注意我在jsFiddle中使用的更有效的数组声明语法。
发布于 2012-11-23 01:12:42
在我看来,一个好方法是使用indexOf()方法在数组中的每个元素中搜索单词,比如月、日、周等。然后使用indexOf搜索数字。要提取文本,可以使用substring。例如,对于字符串'1-2周前‘,你应该说str.substring(0,indexOf '-'),所以这将得到从第一个字符到破折号的所有内容。所以你应该提取第一个数字,即使它是一个3位或4位的数字。(您还可以捕获'-‘字符,因此它可能必须是indexOf('-') -1。研究一下。)
这样做的一个好方法是,在数组中搜索最大的时间单位。查找任何带有“年”的内容,如果没有找到,则搜索“月”,等等。然后创建一个临时数组,并复制包含当前查找的时间单位的所有元素。因此,对于您的示例,您将搜索年份,查找无,搜索月份,找到包含单词month(s)的1个元素,并将其移动到temp数组中。然后,您将分析temp数组中的所有元素,并找到具有最大数字的元素。因此,在您的示例中,您将只有一个,但假设您的答案如下所示
answer1 = { Id: 1, Text: '3-4 weeks ago' },
answer2 = { Id: 2, Text: '1-2 weeks ago' },
answer3 = { Id: 3, Text: '7-8 weeks ago' },
answer4 = { Id: 4, Text: '6 months ago' },
answer5 = { Id: 5, Text: '5-6 weeks ago' },
answer6 = { Id: 6, Text: '1-2 days ago' },
answer7 = { Id: 7, Text: ' 1 month ago' };
answer8 = { Id: 8, Text: ' 3 months ago' };
然后你有3个元素,以月为单位,你会查看所有3个元素,并根据数字对它们进行排序,所以6个月,3个月,1个月。然后,第三个也是最后一个数组用于排序,或者只是重新排列主数组。我认为一个新的“排序”数组会工作得更好。因此,您可以将这3个元素和month单位放入新的排序数组中。
然后转到weeks,找到包含weeks的4个元素,将它们移到temp数组中,分析其中的数字,按大小排序,然后将它们放入排序的数组中,然后移动到days,依此类推。
不管怎么说,htp有一点
https://stackoverflow.com/questions/13517089
复制相似问题