基于整数数组对 JavaScript 字符串数组进行排序

3
在JavaScript中,我有一个数组:
letterArray ['a', 'e', 'i', 'o', 'u']

对应于那个数组,我还有另一个数组:

valueArray [12, 22, 7, 7, 3]

我想要将 valueArray 进行排序,

[22, 12, 7, 7, 3]

但是letterArray也需要按照相同的方式进行排序:
['e', 'a', 'i', 'o', 'u']

我该如何做到这一点?
6个回答

2
方法1:将两个数组压缩成一个类似于[[12,'a'], [22, 'e'], [7, 'i'], [7, 'o'], [3, 'u']]的压缩数组,然后对结果数组进行排序。然后只需读取字母即可。这种方法的优点是可以使用内置的排序算法,您只需要编写访问器。
方法2:自己编写排序算法,并且每次执行更改整数数组的操作时,对字母数组执行相应的操作。
我建议使用方法1。

那可能会解决问题... 只是:如何声明类似的东西?如何基于整数对其进行排序?如何从中读取数据? - Matthias
1
打包它:letterArray.map(function(e,i){return [e,valueArray[i]]}) - Dan Manastireanu
1
进行排序:map.sort(function(e1,e2){return e1[1]-e2[1];}) - Dan Manastireanu
@DanManastireanu 仅支持ES5!:( - Raynos
没错,@Dan Manastireanu说得对。Array.map函数是javascript 1.6中的新函数,所以如果你担心兼容性问题,可以考虑使用Underscore或类似的库。 - Paul Z
显示剩余3条评论

2
你可以使用压缩方法来实现。我会使用_.zip
// [["a", 12], ["e", 22], ...]
var arr = _.zip(letterArray, valueArray); // zip them up.
// sort
// [["u", 3], ["i", 7] OR ["o", 7], ...]
var sortedArr = _.sortBy(arr, function(val) {
    // sort by the value array.
    return val[1];
});
// pluck the letter array back out
// ["u", "i" OR "o", ...]
var newLetterArray = _.pluck(sortedArr, "0");
// pluck the value array back out
// [3, 7, 7, ...]
var newValueArray = _.pluck(sortedArr, "1");

很遗憾,您的示例存在重复数字,这意味着您无法保证排序的顺序。这取决于浏览器,“i”或“o”先出现。


1
我也写了几乎一样的东西。试试这个!Underscore.js非常棒。 - YXD
1
@MrE总是使用下划线。无处不在。这比jQuery更有用! - Raynos

1
// myArray.zip interleaves N arrays into one array of all pieces
// e.g. [1,2,3].zip([4,5,6],[7,8,9]) -> [ [1,4,7], [2,5,8], [3,6,9] ]
(function(o){
  var zip = function(){
    var argLen = arguments.length;
    var result = new Array(this.length);
    for (var i=this.length-1;i>=0;--i){
    var a = result[i] = [this[i]];
    for (var j=0;j<argLen;++j) a[j+1] = arguments[j][i];
    }
    return result;
  }
  if (Object.defineProperty) Object.defineProperty(o,"zip",{value:zip});
  else o.zip = zip;
})(Array.prototype);

var letters = ['a', 'e', 'i', 'o', 'u'];
var values  = [12, 22, 7, 7, 3];
var valuesAndLetters = values.zip(letters);
// [[12,"a"],[22,"e"],[7,"i"],[7,"o"],[3,"u"]]

var sorted = valuesAndLetters.sort(function(a,b){
  // Sort in descending order, first by value, then by letter
  return a[0]<b[0]?1:a[0]>b[0]?-1:a[1]<b[1]?1:a[1]>b[1]?-1:0;
});
// [[22,"e"],[12,"a"],[7,"o"],[7,"i"],[3,"u"]]

编辑:如果您没有(或不想依赖)defineProperty,并且不想将Array.prototype作为后备方案进行扩展,则这里有一个版本的zip函数,它不会影响任何人的原型:

// Interleaves N arrays into one array of all pieces
// e.g. Array.zip([1,2,3],[4,5,6],[7,8,9]) -> [ [1,4,7], [2,5,8], [3,6,9] ]
Array.zip = function zip(a0,a1,etc,aN){
  var argLen = arguments.length;
  var result = new Array(a0.length);
  for (var i=a0.length-1;i>=0;--i){
    var a = result[i] = [a0[i]];
    for (var j=1;j<argLen;++j) a[j] = arguments[j][i];
  }
  return result;
};

var letters = ['a', 'e', 'i', 'o', 'u'];
var values  = [12, 22, 7, 7, 3];
var valuesAndLetters = Array.zip(values,letters);
// [[12,"a"],[22,"e"],[7,"i"],[7,"o"],[3,"u"]]

var sorted = valuesAndLetters.sort(function(a,b){
  // Sort in descending order, first by value, then by letter
  return a[0]<b[0]?1:a[0]>b[0]?-1:a[1]<b[1]?1:a[1]>b[1]?-1:0;
});
// [[22,"e"],[12,"a"],[7,"o"],[7,"i"],[3,"u"]]

我们如何看待扩展本地原型? - Raynos
@Raynos,我们无尽地喜欢它,除非扩展Object.prototype,因为jQuery使用所有黑科技来避免这样做。哦,而且我们应该使用defineProperty,以便它们不可枚举。该死,我会更新的 :) - Phrogz
你知道有多少人在他们的数组上使用 for ... in 并为他们浪费的调试时间而哭泣吗?这真的不值得。另一方面,使用 Array.zip = ... 是值得做的。 - Raynos
@Raynos 感谢你的推动,让我练习了 defineProperty 版本,并且感谢你提供了一个基于数组命名空间的版本的建议。然而,我对那些天真地在数组上使用 for...in 的初学者程序员真的没有同情心。 - Phrogz
+1 @Phrogz,喜欢(a0,a1,etc,aN)这种自我记录无限参数的方式。 - Raynos

0
function odd_way_to_sort(intArr, charArr){
    var min = intArr[0]
    for(index in intArr){
        //some sort of sorting
        // where you save the indexes and then match them to corresponding char Arr indexes
    }
}

你的答案基本上是一个空函数定义,什么都没有。并不是非常有用! - Lightness Races in Orbit
4
它使用了一个数组上的for ... in循环!你真是太丢人了! - Raynos
@Tomalak,我本来想写一个完整的排序算法,但后来觉得这样做是徒劳无益的... - Naftali

0

压缩方式是一种简单的方式,但为了完整起见,另一种方法是使用索引数组:

var letterArray = ['a', 'e', 'i', 'o', 'u'];
var valueArray = [12, 22, 7, 7, 3];
var indexArray = [0, 1, 2, 3, 4]; // normally you would compute this dynamically
indexArray.sort(function(a, b) { return valueArray[a] - valueArray[b]; });

要检索按值顺序排序的字母数组,您需要通过indexArray循环并检索每个索引处的字母。

0
如果我要这样做,而不是使用两个数组,我会使用一个对象数组。然后,您可以编写自己的排序比较函数,这将使您对数据结构拥有最大的控制权。
letters_and_values = [{letter: 'a', value: 12},
                      {letter: 'e', value: 22},
                      {letter: 'i', value: 7},
                      {letter: 'o', value: 7},
                      {letter: 'u', value: 3}];

function valueCompare(obj1, obj2) {
    if (obj1.value < obj2.value) {
        return 1;
    }
    else if (obj1.value > obj2.value) {
        return -1;
    }
    else { 
        return 0;
    }
}

letters_and_values.sort(valueCompare);

// => [Object { letter="e", value=22}, 
//     Object { letter="a", value=12},
//     Object { letter="i", value=7}, 
//     Object { letter="o", value=7}, 
//     Object { letter="u", value=3}]

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