sort()在mozilla&中无法正常工作歌剧

时间:2013-03-24 15:53:57

标签: javascript arrays sorting

我需要对一个数组进行排序,但它只能在Chrome中正常运行。在mozilla规范中,我发现了这个文本,但无法解决这个问题:

  

“此数组的元素已排序。排序不一定   稳定(即,比较相等的元素不一定保留   按原来的顺序)。如果comparefn未定义,则应该是   一个接受两个参数x和y并返回负数的函数   如果x< y,如果x = y则为零,或者如果x> y则为正值; Y“。

此链接https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort可能会帮助您和我

这是我的代码

arr.sort(sortTrip); 

function sortTrip(a, b) {   

    if (a.to != b.from) return 1;
    if (a.to == b.from) return -1;

}

这是arr

var arr = [
    {
        "from": "Moscow",
        "to": "Rome",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    },
    {
        "from": "Oslo",
        "to": "Paris",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    },
    {
        "from": "Helsinki",
        "to": "Tokio",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    },
    {
        "from": "Tokio",
        "to": "Moscow",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    },
    {
        "from": "Paris",
        "to": "New-York",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    },
    {
        "from": "Rome",
        "to": "Oslo",
        "transport": "NSB Regiontog Train",
        "seat": "25"
    }
]

结果必须是

  • 赫尔辛基 - Tokio
  • Tokio - 莫斯科
  • 莫斯科 - 罗马
  • 罗马 - 奥斯陆
  • 奥斯陆 - 巴黎
  • 巴黎 - 纽约

2 个答案:

答案 0 :(得分:4)

  

另见Sorting in JavaScript: Should every compare function have a "return 0" statement?


if (a.to != b.from) return 1;
if (a.to == b.from) return -1;

这不是一致的比较函数(违反反身性,例如compare(x, x) == 0)。你期望它做什么?

引用ES5.1 spec on sort

  

如果comparefn不是该数组元素的一致比较函数,则sort的行为是实现定义的。

     

如果所有值comparefnS和{满足以下所有要求,则函数a是一组值b的一致比较函数集合c中的{1}}(可能是相同的值):符号S表示a <CF b; comparefn(a,b) < 0表示a =CF b(任一标志); comparefn(a,b) = 0表示a >CF b

     

当给定一对特定值comparefn(a,b) > 0comparefn(a,b)作为其两个参数时,调用v始终返回相同的值a。此外,b是数字,Type(v)不是v。请注意,这意味着对于给定的NaNa <CF b对,a =CF ba >CF ba中只有一个为真。

     
      
  • 调用b不会修改此对象。
  •   
  • comparefn(a,b)(反身性)
  •   
  • 如果a =CF a,则a =CF b(对称)
  •   
  • 如果b =CF aa =CF b,则b =CF ca =CF c的及物性传承
  •   
  • 如果=CFa <CF b,则b <CF ca <CF c的及物性传承
  •   
  • 如果<CFa >CF b,则b >CF ca >CF c的及物性传承
  •   
     

注意:上述条件是必要且足以确保>CF将集合comparefn划分为等价类,并且这些等价类是完全有序的。

答案 1 :(得分:0)

我的另一个答案解释了为什么你的排序不稳定。这个将解决您的实际问题: - )

您不能使用sort来解决此类问题,您需要从(无序)边集构造节点列表。只有在没有附加数据的情况下比较两个元素时,才能对数组进行排序。假设您只有两个连接Tokio - MoscowRome - Oslo,您不知道哪个连接是第一个(没有联系您的计划,但您还没有联系)。相比之下,在比较数字时,您可以轻松地并且始终告诉5大于3(通过计算差异)。

相反,我们需要执行类似thisthis的操作 - 构建一个结构,我们可以通过名称轻松访问工作站,并在循环中遇到它们时直接插入连接,以便在最后我们有一个车站连接列表:

var map = {};
for (var i=0; i<arr.length; i++) {
    var con = arr[i];
    map[con.from] = con;
}

这样我们现在可以将您的路线构建为某种链接列表:

for (var from in map) {
    var connTo = map[from].to;
    if (connTo in map)
        map[from].next = map[connTo];
}

通过从地图中删除所有目的地来找到起始站:

for (var from in map)
    for (var next = map[from]; next; next = next.next)
         delete map[next.to];
for (from in map) // there's only one key left
    var start = from; // "Helsinki"

让我们将路径构建为一个站名数组:

var route = [start],
    conn = map[start];
while (conn) {
    route.push(conn.to)
    conn = conn.next;
    // maybe delete conn.next as we don't need it any more
}
// route:
// ["Helsinki", "Tokio", "Moscow", "Rome", "Oslo", "Paris", "New-York"]

或您想要的结果,连接列表:

var arr = [];
for (var conn = map[start]; conn; conn = conn.next)
    arr.push(conn);

有了这个计划,我们现在甚至可以构建一个比较函数来对原始数组进行排序:

arr.sort(function(a, b) {
    // compare the positions of the departure stations in the route
    return route.indexOf(a.from) - route.indexOf(b.from);
});