如何在javascript中最有效地使用datetime合并和排序dicts数组?

时间:2013-06-27 04:08:27

标签: javascript

假设我有以下3个数组,这些数组按exercisedateandtime的升序排序:

var listA = [
  {name: "Mike", exercisedateandtime: 1299233593000, exercise: "Jumping Jacks"}, 
  {name: "Mike", exercisedateandtime: 1299237012000, exercise: "Running"}
];

var listB = [
  {name: "Charles", exercisedateandtime: 1299233712000, exercise: "Swimming"},
  {name: "Charles", exercisedateandtime: 1299233831000, exercise: "Swimming"},
  {name: "Charles", exercisedateandtime: 1299240620000, exercise: "Swimming"}
];

var listC = [
{name: "William", exercisedateandtime: 1299237320000, exercise: "Fishing"},
{name: "William", exercisedateandtime: 1299237611000, exercise: "Motor Boating"},
{name: "William", exercisedateandtime: 1299305420000, exercise: "Cycling"}
];

合并这些列表的最有效方法是什么,这样我得到的结果数组listD也按exercisedateandtime的升序排序?是否可以创建一个接受任意数量数组的函数? (注意:虽然提供的样本很小,但理想的方法应该是处理大的列表大小。)

var listD = [
{name: "Mike", exercisedateandtime: 1299233593000, exercise: "Jumping Jacks"},
{name: "Charles", exercisedateandtime: 1299233712000, exercise: "Swimming"},
{name: "Charles", exercisedateandtime: 1299233831000, exercise: "Swimming"},
{name: "Mike", exercisedateandtime: 1299237012000, exercise: "Running"},
{name: "William", exercisedateandtime: 1299237320000, exercise: "Fishing"},
{name: "William", exercisedateandtime: 1299237611000, exercise: "Motor Boating"},
{name: "Charles", exercisedateandtime: 1299240620000, exercise: "Swimming"},
{name: "William", exercisedateandtime: 1299305420000, exercise: "Cycling"}
];

4 个答案:

答案 0 :(得分:3)

var listD = listA.concat(listB, listC).sort(function(a, b) {
    return a.exercisedateandtime - b.exercisedateandtime
});

答案 1 :(得分:1)

这似乎只是对正常mergesort中的合并进行了轻微调整(在O(n)中运行)。基本上,它是如何工作的,你继续查看每个列表的开头,并采取最大的最小的一个附加到新的列表,它对三个列表完全相同。所以这是来自Aadit解决方案的代码(与我的相同算法),但是每个人似乎都在投票一个比这个解决方案慢得多的解决方案,我想反击这个,所以OP不会最终使用它在他的代码中。

function merge(key) {
    var length = arguments.length, lists = [], newlist = [];
    for (var i = 1; i < length; i++) lists.push(arguments[i].slice());

    while (length = lists.length) {
        var min = Infinity;

        for (var i = 0; i < length; i++) {
            var list = lists[i];
            var value = list[0][key];

            if (value < min) {
                var index = i;
                min = value;
            }
        }

        var list = lists[index];
        newlist.push(list.shift());
        if (!list.length) lists.splice(index, 1);
    }

    return newlist;
}

现在您可以按如下方式合并列表:

var listD = merge("exercisedateandtime", listA, listB, listC);  

基本上这是如何工作的是获取列表列表和它应该排序的键,在本例中为exercisedateandtime。然后它继续找到所有列表的最小前元素,直到没有列表为止(while循环有点棘手,因为=返回lists为0时设置的值。它变得虚假)。即使它们的大小不同,此合并也适用于任意数量的列表。该算法在O(n)中运行,假设列表大小足以使列表数量可忽略不计。

编辑:在非常不理想的情况下,列表的数量非常大,而这里不是这种情况,因为只有三个列表,每个列表的大小很小,可能是更好地做一个合并列表的解决方案,就像合并排序一样,一次2个。可以通过检查列表的数量来调整代码,但是编写代码会更多。我还要再重复一次,原来的问题是针对3个列表,所以它可以正常工作。

以下是我能找到的最理想n-way merge的链接

答案 2 :(得分:1)

是的,的确如此。试试这个:

function merge(key) {
    var length = arguments.length, lists = [], newlist = [];
    for (var i = 1; i < length; i++) lists.push(arguments[i].slice());

    while (length = lists.length) {
        var min = Infinity;

        for (var i = 0; i < length; i++) {
            var list = lists[i];
            var value = list[0][key];

            if (value < min) {
                var index = i;
                min = value;
            }
        }

        var list = lists[index];
        newlist.push(list.shift());
        if (!list.length) lists.splice(index, 1);
    }

    return newlist;
}

现在您可以按如下方式合并列表:

var listD = merge("exercisedateandtime", listA, listB, listC);

请参阅此处的演示:http://jsfiddle.net/b8WdW/2/

答案 3 :(得分:0)

Fiddle

基本上我在排序前先合并了数组。因此,即使数组未排序,这也应该有效。

var listD = listB.concat(listA, listC);
console.log(listD);
listD.sort(function (a, b) {
return a.exercisedateandtime - b.exercisedateandtime
});
console.log(listD);