在Javascript中如何根据关联数组的值对其排序?

在Javascript中如何根据关联数组的值对其排序?,javascript,arrays,sorting,associative,Javascript,Arrays,Sorting,Associative,我有关联数组: array["sub2"] = 1; array["sub0"] = -1; array["sub1"] = 0; array["sub3"] = 1; array["sub4"] = 0; 按其值排序(降序)的最优雅方式是什么?结果将是一个按此顺序包含相应索引的数组: sub2, sub3, sub1, sub4, sub0 JavaScript中确实没有“关联数组”这样的东

我有关联数组:

array["sub2"] = 1;
array["sub0"] = -1;
array["sub1"] = 0;
array["sub3"] = 1;
array["sub4"] = 0;
按其值排序(降序)的最优雅方式是什么?结果将是一个按此顺序包含相应索引的数组:

sub2, sub3, sub1, sub4, sub0

JavaScript中确实没有“关联数组”这样的东西。你所得到的只是一个普通的旧物体。当然,它们的工作方式有点像关联数组,键是可用的,但键的顺序没有语义

您可以将对象转换为对象数组(键/值对),并对其进行排序:

function sortObj(object, sortFunc) {
  var rv = [];
  for (var k in object) {
    if (object.hasOwnProperty(k)) rv.push({key: k, value:  object[k]});
  }
  rv.sort(function(o1, o2) {
    return sortFunc(o1.key, o2.key);
  });
  return rv;
}
然后你可以用一个比较器函数来调用它。

Javascript没有你所认为的“关联数组”。相反,您只需要能够使用类似数组的语法设置对象属性(如您的示例中所示),并能够迭代对象的属性

这样做的结果是,无法保证迭代属性的顺序,因此没有什么比排序更好的了。相反,您需要将对象属性转换为“true”数组(这可以保证顺序)。下面是一段代码片段,用于将对象转换为两个元组(两个元素数组)的数组,按照描述对其进行排序,然后对其进行迭代:

var tuples = [];

for (var key in obj) tuples.push([key, obj[key]]);

tuples.sort(function(a, b) {
    a = a[1];
    b = b[1];

    return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < tuples.length; i++) {
    var key = tuples[i][0];
    var value = tuples[i][1];

    // do something with key and value
}
var tuples=[];
对于(对象中的var key)元组,push([key,obj[key]]);
tuples.sort(函数(a,b){
a=a[1];
b=b[1];
返回ab-1:0);
});
for(var i=0;i
您可能会发现,将其封装在接受回调的函数中更为自然:

函数bySortedValue(对象、回调、上下文){
变量元组=[];
对于(对象中的var key)元组,push([key,obj[key]]);
tuples.sort(函数(a,b){
返回a[1]b[1]?-1:0
});
var length=tuples.length;
while(length--)callback.call(context,tuples[length][0],tuples[length][1]);
}
bySortedValue({
傅:1,,
酒吧:7,
巴兹:3
},函数(键,值){
document.getElementById('res').innerHTML+=`${key}:${value}
` });

结果:

我使用$。每个jquery都可以使用for循环,改进如下:

        //.ArraySort(array)
        /* Sort an array
         */
        ArraySort = function(array, sortFunc){
              var tmp = [];
              var aSorted=[];
              var oSorted={};

              for (var k in array) {
                if (array.hasOwnProperty(k)) 
                    tmp.push({key: k, value:  array[k]});
              }

              tmp.sort(function(o1, o2) {
                    return sortFunc(o1.value, o2.value);
              });                     

              if(Object.prototype.toString.call(array) === '[object Array]'){
                  $.each(tmp, function(index, value){
                      aSorted.push(value.value);
                  });
                  return aSorted;                     
              }

              if(Object.prototype.toString.call(array) === '[object Object]'){
                  $.each(tmp, function(index, value){
                      oSorted[value.key]=value.value;
                  });                     
                  return oSorted;
              }               
     };
所以现在你可以做了

    console.log("ArraySort");
    var arr1 = [4,3,6,1,2,8,5,9,9];
    var arr2 = {'a':4, 'b':3, 'c':6, 'd':1, 'e':2, 'f':8, 'g':5, 'h':9};
    var arr3 = {a: 'green', b: 'brown', c: 'blue', d: 'red'};
    var result1 = ArraySort(arr1, function(a,b){return a-b});
    var result2 = ArraySort(arr2, function(a,b){return a-b});
    var result3 = ArraySort(arr3, function(a,b){return a>b});
    console.log(result1);
    console.log(result2);       
    console.log(result3);

我认为这是你想要的,而不是纠正你关于“关联数组”的语义:

function getSortedKeys(obj) {
    var keys = keys = Object.keys(obj);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}
对于,请改用此选项:

function getSortedKeys(obj) {
    var keys = []; for(var key in obj) keys.push(key);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}
您转储一个对象(像您的对象)并获得一个键数组-eh properties-back,按对象的值(数字)降序排序


这仅在值为数字时有效。t查看其中的小
函数(a,b)
,将排序机制更改为升序,或处理
字符串
值(例如)。留给读者作为练习。

继续讨论和其他解决方案,最好的解决方案(针对我的情况)是by(以下引用)

数组只能有数字索引。您需要将其重写为对象或对象数组

var status = new Array();
status.push({name: 'BOB', val: 10});
status.push({name: 'TOM', val: 3});
status.push({name: 'ROB', val: 22});
status.push({name: 'JON', val: 7});
如果您喜欢
status.push
方法,可以使用以下方法进行排序:

status.sort(function(a,b) {
    return a.val - b.val;
});

如果你不喜欢元组,这里是ben blank答案的一个变体

这样可以节省几个字符

var keys = [];
for (var key in sortme) {
  keys.push(key);
}

keys.sort(function(k0, k1) {
  var a = sortme[k0];
  var b = sortme[k1];
  return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < keys.length; ++i) {
  var key = keys[i];
  var value = sortme[key];
  // Do something with key and value.
}
var-keys=[];
for(sortme中的var键){
按键。按(键);
}
键。排序(函数(k0,k1){
var a=sortme[k0];
var b=排序[k1];
返回ab-1:0);
});
对于(变量i=0;i
无需任何不必要的复杂性

function sortMapByValue(map)
{
    var tupleArray = [];
    for (var key in map) tupleArray.push([key, map[key]]);
    tupleArray.sort(function (a, b) { return a[1] - b[1] });
    return tupleArray;
}
@commonpike的回答是“正确的”,但随着他继续评论

现在大多数浏览器只支持
Object.keys()

Object.keys()
更好

但是什么比这更好呢?嗯,是在
coffeescript

sortedKeys = (x) -> Object.keys(x).sort (a,b) -> x[a] - x[b]

sortedKeys
  'a' :  1
  'b' :  3
  'c' :  4
  'd' : -1
['d','a','b','c']


就这样,有人在寻找基于元组的排序。 这将比较数组中对象的第一个元素和第二个元素,依此类推。i、 e在下面的示例中,它将首先通过“a”进行比较,然后通过“b”进行比较,依此类推

let arr = [
    {a:1, b:2, c:3},
    {a:3, b:5, c:1},
    {a:2, b:3, c:9},
    {a:2, b:5, c:9},
    {a:2, b:3, c:10}    
]

function getSortedScore(obj) {
    var keys = []; 
    for(var key in obj[0]) keys.push(key);
    return obj.sort(function(a,b){
        for (var i in keys) {
            let k = keys[i];
            if (a[k]-b[k] > 0) return -1;
            else if (a[k]-b[k] < 0) return 1;
            else continue;
        };
    });
}

console.log(getSortedScore(arr))

在我看来,针对具体案例的最佳方法是commonpike建议的方法。我建议在现代浏览器中使用的一点改进是:

// aao is the "associative array" you need to "sort"
Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});
这可以很容易地应用,并且在这里的特定情况下非常有效,因此您可以:

let aoo={};
aao["sub2"]=1;
aao["sub0"]=-1;
aao["sub1"]=0;
aao["sub3"]=1;
aao["sub4"]=0;

let sk=Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});

// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}
除此之外,我在这里提供了一个更“通用”的函数,您甚至可以在更广泛的情况下使用它进行排序,它将我刚才建议的改进与Ben Blank(对字符串值进行排序)和PopeJohnPaulII(按特定对象字段/属性进行排序)的方法相结合让你决定你想要的是上升顺序还是下降顺序,这里是:

// aao := is the "associative array" you need to "sort"
// comp := is the "field" you want to compare or "" if you have no "fields" and simply need to compare values
// intVal := must be false if you need comparing non-integer values
// desc := set to true will sort keys in descendant order (default sort order is ascendant)
function sortedKeys(aao,comp="",intVal=false,desc=false){
  let keys=Object.keys(aao);
  if (comp!="") {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]-aao[a][comp]});
      else return keys.sort(function(a,b){return aao[a][comp]-aao[a][comp]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]<aao[a][comp]?1:aao[b][comp]>aao[a][comp]?-1:0});
      else return keys.sort(function(a,b){return aao[a][comp]<aao[b][comp]?1:aao[a][comp]>aao[b][comp]?-1:0});
    }
  } else {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b]-aao[a]});
      else return keys.sort(function(a,b){return aao[a]-aao[b]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b]<aao[a]?1:aao[b]>aao[a]?-1:0});
      else return keys.sort(function(a,b){return aao[a]<aao[b]?1:aao[a]>aao[b]?-1:0});
    }
  }
}
正如我已经说过的,如果你需要做一些事情,你可以在排序过的键上循环

let sk=sortedKeys(aoo);
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}

最后,但并非最不重要的一点是,对和的一些有用的引用,因为对象属性没有语言定义的顺序-你不能(除了,也许在一些JS引擎中,取决于它们实现属性的特定方式)。+1你比我强。我正在写一个非常类似的解释和一段代码@stot-如果您的值都是数字(如询问者的示例),则绝对是。我似乎心不在焉地提供了一个同样适用于字符串的比较函数。:-)@本:是的,你说得对,提供的版本更一般;-)@本,非常感谢你的发帖。关于字符串比较函数,它是否使用ASCII值比较?@jjwdesign,假设字符串尚未编码,它将按Unicode码点排序。非常好!要对名称进行排序和alpha排序:返回a.name>b.name.F
let items={};
items['Edward']=21;
items['Sharpe']=37;
items['And']=45;
items['The']=-12;
items['Magnetic']=13;
items['Zeros']=37;
//equivalent to:
//let items={"Edward": 21, "Sharpe": 37, "And": 45, "The": -12, ...};

console.log("1: "+sortedKeys(items));
console.log("2: "+sortedKeys(items,"",false,true));
console.log("3: "+sortedKeys(items,"",true,false));
console.log("4: "+sortedKeys(items,"",true,true));
/* OUTPUT
1: And,Sharpe,Zeros,Edward,Magnetic,The
2: The,Magnetic,Edward,Sharpe,Zeros,And
3: The,Magnetic,Edward,Sharpe,Zeros,And
4: And,Sharpe,Zeros,Edward,Magnetic,The
*/

items={};
items['k1']={name:'Edward',value:21};
items['k2']={name:'Sharpe',value:37};
items['k3']={name:'And',value:45};
items['k4']={name:'The',value:-12};
items['k5']={name:'Magnetic',value:13};
items['k6']={name:'Zeros',value:37};

console.log("1: "+sortedKeys(items,"name"));
console.log("2: "+sortedKeys(items,"name",false,true));
/* OUTPUT
1: k6,k4,k2,k5,k1,k3
2: k3,k1,k5,k2,k4,k6
*/
let sk=sortedKeys(aoo);
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}