下划线多维排序

Underscore multidimensional sortBy

我有对象

[
    { "home1": { "mesafe":11 } },
    { "home2": { "mesafe": 6 } },
    { "home3": { "mesafe":42 } },
    { "home4": { "mesafe":23 } },
    { "home5": { "mesafe": 5 } }
]

如何使用下划线按 ASC 数字的 mesafe 字段顺序对该对象进行排序?

您可以使用 JavaScript Array sort() Method 根据 mesafe 字段中的值对数组进行排序。

var data = [
    { "home1": { "mesafe":11 } },
    { "home2": { "mesafe": 6 } },
    { "home3": { "mesafe":42 } },
    { "home4": { "mesafe":23 } },
    { "home5": { "mesafe": 5 } }
];

// get the value from mesafe field
function getMesafeValue(a) {
  for (var key in a) {
    if (a.hasOwnProperty(key)) {
      return a[key].mesafe;
    }
  }
}

// sort the array
data.sort(function(a, b) {

  var v1 = getMesafeValue(a);
  var v2 = getMesafeValue(b);

  return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0);
});

// print the array after sorting
for (var i = 0; i < data.length; i++) {
  for (var key in data[i]) {
    if (data[i].hasOwnProperty(key)) {
      document.write(key + " -> " + data[i][key].mesafe + '<br/>');
    }
  }
}

可以考虑

{
  "home1": {
    "mesafe":11 
  }
} 

作为

{
  "home1": {
    "mesafe":11 
  }, 
  // fakes
  "home2": {},  
  "home3": {}...
}

现在要排序的值可以描述为:

从子对象中获取所有 mesafe 属性的值并将它们相加(如果该属性存在)。

所以可以用_.reduce来实现

var list = [
    { "home1": { "mesafe":11 } },
    { "home2": { "mesafe": 6 } },
    { "home3": { "mesafe":42 } },
    { "home4": { "mesafe":23 } },
    { "home5": { "mesafe": 5 } }
];

var sortedList = _.sortBy(list, function(item) {
  
  // For each item, we acts as  there not only have one attribute "homex", but there's many other like "homey : {}".
  var res =  _.reduce(item, function(res, sub) {
    // So we can the again use reduce to iterate through them, and add the value if mesafe exist.
    return (sub.mesafe == null) ? res : res + sub.mesafe;
  }, 0);
  
  return res;
});

console.log(sortedList);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>