我对我正在进行的项目有一个要求,这对我来说有点棘手。
基本上我必须根据这些项目的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服务返回的,我没有能力更改文本。所以我必须按原样使用它。
答案 0 :(得分:2)
您可以使用自定义排序函数来解析文本中的值,并按照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);
});
})()
P.S。请注意我在jsFiddle中使用的更有效的数组声明语法。
答案 1 :(得分:0)
在我看来,一个好方法,使用indexOf()方法并搜索数组中的每个元素,如月,日,周等等。然后在使用indexOf搜索数字之后。要提取文本,您可以使用子字符串。所以例如对于字符串'1-2周前'你会说str.substring(0,indexOf' - ')所以这将得到从第一个字符到破折号的所有内容。因此,即使它是3位或4位数字,您也可以提取第一个数字。 (你也可能会抓住' - '字符,所以它可能必须是indexOf(' - ') - 1 ..研究那个。)
这是一个很好的方法,搜索数组中最大的单位时间..查找任何带有'年'的内容,如果没有找到,搜索几个月等等。然后有一个临时数组并复制所有元素包含您当前正在寻找的时间单位。因此,对于您的示例,您将搜索多年,找不到,搜索几个月,找到包含单词month(s)的1个元素,并将其移动到临时数组中。然后你要分析你的临时数组中的所有元素,找到数字最大的元素。所以在你的例子中你只有一个,但你的答案看起来像是
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个和最后一个数组,或者只是重新安排主数组。我认为一个新的'Sorted'数组会更好。所以你将这3个带月份单位的元素放入新的排序数组中。
然后你会去几个星期,你会发现有4周的4个元素,将它们移动到临时数组,分析它们中的数字,按大小排序,然后将它们粘贴在已排序的数组中,然后移动到了等等......
htp一点点反正