按字母顺序排序数组,但有例外

时间:2016-07-19 03:10:22

标签: javascript arrays

我有以下数组结构

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

我想重新排序数组,使其按以下顺序排列:Profile PicturesMobile UploadsInstagram Photos,以及之后的对象按照基本顺序排列。

3 个答案:

答案 0 :(得分:6)

您要做的是创建一个包含排序异常的对象。然后,您可以编写一个自定义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 :(得分: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));

这个想法是指定权重来管理排序。

答案 2 :(得分: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