0

我对我现在正在从事的项目有一个要求,这对我来说有点棘手。

基本上我必须根据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 周”。

所以逻辑是,我需要提取数值,然后是单位(例如天、周),并根据这些细节以某种方式对数组进行排序。

老实说,我发现很难提出解决方案,我将不胜感激。

编辑:关于我正在使用的数据,它是从网络服务返回的,我没有能力更改文本。所以我必须按原样使用它。

4

2 回答 2

2

您可以使用自定义排序函数来解析文本中的值并按此处所述对它们进行数字比较。

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);
    });
})()

PS 请注意我在 jsFiddle 中使用的更有效的数组声明语法。

于 2012-11-22T17:00:11.717 回答
0

在我看来,一个好方法,使用 indexOf() 方法并在数组中的每个元素中搜索单词,如月、日、周等。然后使用 indexOf 搜索数字。要提取文本,您可以使用子字符串。例如,对于字符串 '1-2 周前',你会说 str.substring(0, indexOf '-') 所以这会得到从第一个字符到破折号的所有内容。所以你会提取他的第一个数字,即使它是 3 或 4 位数字。(您可能还抓住了“-”字符,所以它可能必须是 indexOf('-') - 1 .. 研究一下。)

一个很好的方法是在数组中搜索最大的时间单位。查找带有“年”的任何内容,如果没有找到,请搜索月份等。然后有一个临时数组并复制所有包含您当前正在寻找的时间单位。因此,对于您的示例,您将搜索年份,没有找到,搜索月份,找到 1 个包含单词 month(s) 的元素,然后将其移动到 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 个以月份为单位的元素放入新的排序数组中。

然后你会去几个星期,你会找到有周数的 4 个元素,将它们移动到临时数组,分析其中的数字,按大小对它们进行排序,然后将它们粘贴到排序数组中,然后移动到几天ETC..

无论如何,htp

于 2012-11-22T17:12:42.067 回答