如何通过Javascript中的值对关联数组进行排序?

Joh*_*ith 82 javascript arrays sorting associative

我有关联数组:

array["sub2"] = 1;
array["sub0"] = -1;
array["sub1"] = 0;
array["sub3"] = 1;
array["sub4"] = 0;
Run Code Online (Sandbox Code Playgroud)

什么是按其值排序(降序)的最优雅方式,其中结果将是具有相应索引的数组:

sub2, sub3, sub1, sub4, sub0
Run Code Online (Sandbox Code Playgroud)

Ben*_*ank 113

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
}
Run Code Online (Sandbox Code Playgroud)

你可能会发现将它包装在一个需要回调的函数中更自然:

function bySortedValue(obj, callback, context) {
  var tuples = [];

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

  tuples.sort(function(a, b) {
    return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0
  });

  var length = tuples.length;
  while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
}

bySortedValue({
  foo: 1,
  bar: 7,
  baz: 3
}, function(key, value) {
  document.getElementById('res').innerHTML += `${key}: ${value}<br>`
});
Run Code Online (Sandbox Code Playgroud)
<p id='res'>Result:<br/><br/><p>
Run Code Online (Sandbox Code Playgroud)

  • tuples.sort 函数可以清理为 tuples.sort(function(a, b) { return a[1] - b[1]; }); (2认同)
  • @stot - 如果你的值都是数字(如提问者的例子中所示),绝对是.我似乎心不在焉地提供了一个比较函数,它也适用于字符串.:-) (2认同)

com*_*ike 81

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

function getSortedKeys(obj) {
    var keys = keys = Object.keys(obj);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}
Run Code Online (Sandbox Code Playgroud)

你转储到一个对象(比如你的)并得到一个键的数组 - 呃属性 - 返回,按eh,对象的值的(数值)值降序排序.

仅当您的值是数字时才有效.function(a,b)在那里调整一点,将分类机制改为工作升序,或者为string值工作(例如).留给读者练习.

编辑:人们不断提高这个答案,但它确实很老了.请重新考虑为什么你现在不仅仅使用Object.keys():function(a,b)

  • 我应该注意到,现在大多数浏览器只支持 Object.keys() - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys (2认同)
  • ... :) 我累了,让我删除这个 (2认同)

Pop*_*lII 15

如何按值对(关联)数组进行排序,需要继续讨论和解决其他问题最好的解决方案(对于我的情况)是由saml(引用如下).

数组只能有数字索引.您需要将其重写为Object或Object of Array.

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});
Run Code Online (Sandbox Code Playgroud)

如果您喜欢该status.push方法,可以使用以下方法对其进行排序:

status.sort(function(a,b) {
    return a.val - b.val;
});
Run Code Online (Sandbox Code Playgroud)

  • @mpemburn:[不完全没有](http://stackoverflow.com/q/24080785/1048572) (2认同)
  • 对于字母排序,请比较相同大小写的字符串值,因为“sort()”对它们的处理方式不同。它让我困惑了一个小时,直到我找到这个 http://stackoverflow.com/questions/6712034/sort-array-by-firstname-alphabetically-in-javascript#answer-6712058 示例;`a.name.toLowerCase() &gt; b.name.toLowerCase()` (2认同)

Poi*_*nty 5

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;
}
Run Code Online (Sandbox Code Playgroud)

然后你用比较器函数调用它.


dan*_*tra 5

在我看来,针对具体情况的最佳方法是建议的一种普通梭子鱼。我建议在现代浏览器中进行的一点改进是:

// aao is the "associative array" you need to "sort"
Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});
Run Code Online (Sandbox Code Playgroud)

这可以轻松应用,并且在此处的特定情况下效果很好,因此您可以执行以下操作:

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]]
}
Run Code Online (Sandbox Code Playgroud)

除此之外,我在这里提供了一个更“通用”的函数,您可以使用它在更广泛的情况下进行排序,并将我刚刚建议的改进与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});
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以尝试使用以下代码来测试功能:

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
*/
Run Code Online (Sandbox Code Playgroud)

正如我已经说过的,如果您需要做一些事情,您可以循环排序键

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]]
}
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的一点是对Object.keysArray.sort的一些有用引用