按字母顺序对数组进行排序,但有一些例外情况。

5

I have the following array structure

[{
  name: "Mobile Uploads"
}, {
  name: "Profile Pictures"
}, {
  name: "Reports"
}, {
  name: "Instagram Photos"
}, {
  name: "Facebook"
}, {
  name: "My Account"
}, {
  name: "Twitter"
}]

我想重新排列数组,使它按照以下顺序排列: 个人资料图片移动上传Instagram照片,然后按字母顺序排列其他对象。

2
不要考虑移动元素,可以考虑创建一个新的数组,将元素按照所需的顺序放入其中。您可以使用诸如sortmapfilter之类的例程来实现。这是我们通常在JS中做的。顺便说一下,您在这里使用了“高效”这个词。我在JS问题中经常看到这种情况。严格来说,这意味着“快速执行”。这是您的意思吗?还是您真正的意思通常情况下是“以易于阅读和编写的方式”? - user663031
嘿@Brown,所以您正在寻找2个订单: 资料图片,移动上传,Instagram照片和Instagram照片,移动上传,资料图片 - Ayan
2
https://dev59.com/93E95IYBdhLWcg3wI6bt - Venkat
3个回答

10
你需要做的是创建一个包含排序例外的对象。然后,你可以编写一个自定义的 sort() 函数来处理你的例外情况。

var list = [{
  name: "Date"
}, {
  name: "Mobile Uploads"
}, {
  name: "Profile Pictures"
}, {
  name: "Fig"
}, {
  name: "Instagram Photos"
}, {
  name: "Cherry"
}, {
  name: "Apple"
}, {
  name: "Banana"
}];

var exceptions = {
  "Profile Pictures": 1,
  "Mobile Uploads": 2,
  "Instagram Photos": 3
}

list.sort(function(a, b) {
  if (exceptions[a.name] && exceptions[b.name]) {
    //if both items are exceptions
    return exceptions[a.name] - exceptions[b.name];
  } else if (exceptions[a.name]) {
    //only `a` is in exceptions, sort it to front
    return -1;
  } else if (exceptions[b.name]) {
    //only `b` is in exceptions, sort it to back
    return 1;
  } else {
    //no exceptions to account for, return alphabetic sort
    return a.name.localeCompare(b.name);
  }
});

console.log(list);


1
看起来比我的方法更简洁,逻辑更易于理解 +1 - Ultimater

0

我认为最好的方法是使用自定义的sort函数来完成所有操作。排序回调函数会给出两个参数,第一个数组元素和第二个数组元素,它们将进行比较。然后您可以在回调体内使用任何逻辑来决定返回什么。如果返回-1,则表示第一个元素应该在第二个元素之前。如果返回1,则表示第二个元素应该在第一个元素之前。如果返回0,则表示两个元素相等,因此应该保持并排,以便在排序过程中不会插入其他元素。

要按字母顺序排序,您可以使用<><=>=运算符将两个字符串进行比较。然后结果将是布尔值true或false,因此您需要根据您所比较的方式返回-11,具体取决于您想要升序还是降序。您还可以检查相等性并返回0,如果您认为您的数组中会遇到重复项,并且希望有一个稍微快一点的实现,除非您处理大量数据,否则几乎不会注意到。

如果要将异常添加到字母排序中,建议为第一个元素创建一个数字表示,然后为第二个元素创建另一个数字表示。使用负数来指示异常之间的排序,其中数字越小,表示它应该接近数组的开头。然后使用 0 表示其他所有内容都不是异常。最后使用简单的 if 语句检查是否存在异常。如果没有异常,则按字母顺序排序。否则,我们有一个异常,应按较小数字所代表的顺序进行排序。

    

var inputArray = [{
  name: "Mobile Uploads"
}, {
  name: "Profile Pictures"
}, {
  name: "Reports"
}, {
  name: "Instagram Photos"
}, {
  name: "Facebook"
}, {
  name: "My Account"
}, {
  name: "Twitter"
}];

var sortedArray = inputArray.slice(0);//copy of the original array as sort is destructive.
sortedArray.sort(function(a,b){
    var aIndex = 0, bIndex = 0;
    switch(a.name)
    {
        case "Profile Pictures":
            aIndex = -3;
            break;
        case "Mobile Uploads":
            aIndex = -2;
            break;
        case "Instagram Photos":
            aIndex = -1;
            break;
    }
    switch(b.name)
    {
        case "Profile Pictures":
            bIndex = -3;
            break;
        case "Mobile Uploads":
            bIndex = -2;
            break;
        case "Instagram Photos":
            bIndex = -1;
            break;
    }
   if(aIndex < 0 || bIndex < 0)//Check if either element being compared needs special treatment
   {
       //in the case of two exceptions, we want the smallest one to be sorted first
       //otherwise in the case of one exception the other element would be a 0
       return aIndex < bIndex ? -1 : 1;//ascending
   }
   else
   {
       //otherwise just sort in alpabetical order comparing strings with the less than operator
       return a.name < b.name ? -1 : 1;//ascending
   }
});

//Before
console.log('Before:');
console.log(inputArray.map(function(v){
    return v.name;
}).join(', '));//Mobile Uploads, Profile Pictures, Reports, Instagram Photos, Facebook, My Account, Twitter

//After
console.log('After:');
console.log(sortedArray.map(function(v){
    return v.name;
}).join(', '));//Profile Pictures, Mobile Uploads, Instagram Photos, Facebook, My Account, Reports, Twitter


我会避免那种比较。 - Bergi
1
除非数组会遇到重复项,否则返回零是浪费的,即使有重复项,考虑这种情况,数组也可以很好地排序。在OP的问题中,看起来他或她试图构建某种导航栏,该导航栏首先不会有重复项,因此更快的方法是不考虑重复项。 - Ultimater

0
    var algo = [{
        name: "Mobile Uploads"
     },
     { 
        name: "Zeta"
     },
     {
        name: "Beta"
     },
     {
        name: "Alfa"
     },
     { 
        name: "Profile Pictures"
     },
     {
        name: "Instagram Photos"
     }]

var compare = function(a,b){
    var weight = {"Profile Pictures":1, "Mobile Uploads":2, "Instagram Photos":3}
    ,   nameA = a.name
    ,   weightA = weight[nameA] || 100
    ,   nameB = b.name
    ,   weightB = weight[nameB] || 100

    if(weightA != weightB){
        return weightA - weightB;
    }else{
        return nameA > nameB;
    }

}

console.log(algo.sort(compare));

这个想法是分配权重来管理排序。


仅仅使用[return nameA > nameB;]是不够的。 - Bergi
你为什么认为 return nameA > nameB; 不够? - Guillermo F. Lopez
1
只是阅读了链接问题的答案。它不起作用。 - Bergi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接