按值对对象属性进行排序

1008

如果我有一个 JavaScript 对象,例如:

var list = {
  "you": 100, 
  "me": 75, 
  "foo": 116, 
  "bar": 15
};

有没有一种方法可以根据值对属性进行排序?这样我最后会得到:

list = {
  "bar": 15, 
  "me": 75, 
  "you": 100, 
  "foo": 116
};

5
不仅要"排序",更重要的是对数字进行排序。数字不受Javascript的Array.sort()方法影响,这意味着你不仅需要找到一种对属性进行排序的方法,还需要编写自己的函数来比较数值大小。 - Sampson
237
在阅读答案之前:答案是否定的。ECMAScript 中对象属性的顺序是非标准的。您不应该对 JavaScript 对象中元素的顺序做出任何假设。对象是一个无序的属性集合。下面的答案向您展示了如何“使用”已排序的属性,借助于数组的帮助,但实际上从未改变对象本身的属性顺序。所以,不,这是不可能的。即使您构建了具有预排序属性的对象,也不能保证它们将来会以相同的顺序显示。请继续阅读 :)。 - Govind Rai
11
在实际的前端应用程序中,我们使用对象集合的 ID 作为键来循环遍历,并且如果转换为 HTML 模板,则顺序很重要。你说它们没有顺序,我说当我在当前浏览器中使用 console.logging 查看它们时,它们确实有顺序。而且这个顺序可能会被重新排序。一旦你循环遍历它们,它们就会有一个顺序。 - ProblemsOfSumit
9
现在规范中有一种方式可以按指定顺序访问属性。这是一个好主意吗?几乎肯定不是。 :-) 但是它已经存在于ES2015中。 - T.J. Crowder
21
2019年的访客们,可以查看这个仅得到少量赞同的基于Object.entries的答案,它是自ES2017以来最干净、最易读的现代方法:https://dev59.com/LXNA5IYBdhLWcg3wKacx#37607084 - jakub.g
显示剩余5条评论
45个回答

1

另一个示例使用 Object.valuessort()spread 操作符

var paintings = {
    0: {
        title: 'Oh my!',
        year: '2020',
        price: '3000'
    },
    1: {
        title: 'Portrait V',
        year: '2021',
        price: '2000'
    },
    2: {
        title: 'The last leaf',
        year: '2005',
        price: '600'
    }
}

我们使用 Object.values 将对象转换为对象数组:
var toArray = Object.values(paintings)

接下来,我们使用 spread operator 使原始数组不可变,并使用 sort() 方法按年份和价格对数组进行排序:

var sortedByYear = [...toArray].sort((a, b) => a.year - b.year)
var sortedByPrice = [...toArray].sort((a, b) => a.price - b.price)

最后,我们生成新的排序对象(同样使用展开运算符以保留具有[x:number]作为键的对象形式):
var paintingsSortedByYear = {
    ...sortedByYear
}

var paintingsSortedByPrice = {
    ...sortedByPrice
}

希望这对你有所帮助!

1

这是获取排序后对象并返回已排序对象的方法。

let sortedObject = {}
sortedObject = Object.keys(yourObject).sort((a, b) => {
                        return yourObject[a] - yourObject[b] 
                    }).reduce((prev, curr, i) => {
                        prev[i] = yourObject[curr]
                        return prev
                    }, {});

你可以根据自己的需求定制排序函数。

非常好的回答。谢谢! - Gaston Sanchez

1
这是另一个例子:

function sortObject(obj) {
  var arr = [];
  var prop;
  for (prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      arr.push({
        'key': prop,
        'value': obj[prop]
      });
    }
  }
  arr.sort(function(a, b) {
    return a.value - b.value;
  });
  return arr; // returns array
}
var list = {
  car: 300,
  bike: 60,
  motorbike: 200,
  airplane: 1000,
  helicopter: 400,
  rocket: 8 * 60 * 60
};
var arr = sortObject(list);
console.log(arr);


1

查找每个元素的频率并按频率/值进行排序。

let response = ["apple", "orange", "apple", "banana", "orange", "banana", "banana"];
let frequency = {};
response.forEach(function(item) {
  frequency[item] = frequency[item] ? frequency[item] + 1 : 1;
});
console.log(frequency);
let intents = Object.entries(frequency)
  .sort((a, b) => b[1] - a[1])
  .map(function(x) {
    return x[0];
  });
console.log(intents);

输出:

{ apple: 2, orange: 2, banana: 3 }
[ 'banana', 'apple', 'orange' ]

要在TypeScript中使用相同的代码,请修改以下行: .sort((a:any,b:any)= > b [1] - a [1]) 对变量添加任何类型。 - Vignesh G

1

例如输入和输出

{
  "a": 1,
  "b": 4,
  "c": 0,
  "d": 2
}
{
  "b": 4,
  "d": 2,
  "a": 1,
  "c": 0
}

实现

const _ = require('lodash');

const o = { a: 1, b: 4, c: 0, d: 2 };


function sortByValue(object, descending = true) {
  const { max, min } = Math;
  const selector = descending ? max : min;

  const objects = [];
  const cloned = _.clone(object);

  while (!_.isEmpty(cloned)) {
    const selectedValue = selector(...Object.values(cloned));
    const [key, value] = Object.entries(cloned).find(([, value]) => value === selectedValue);

    objects.push({ [key]: value });
    delete cloned[key];
  }

  return _.merge(...objects);
}

const o2 = sortByValue(o);
console.log(JSON.stringify(o2, null, 2));

0

使用query-js,您可以像这样做

list.keys().select(function(k){
    return {
        key: k,
        value : list[k]
    }
}).orderBy(function(e){ return e.value;});

您可以在这里找到有关query-js的介绍性文章here


0
function sortObjByValue(list){
 var sortedObj = {}
 Object.keys(list)
  .map(key => [key, list[key]])
  .sort((a,b) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0)
  .forEach(data => sortedObj[data[0]] = data[1]);
 return sortedObj;
}
sortObjByValue(list);

Github Gist 链接


0

在上面的答案中,我找不到既能正常工作又小巧,并且支持嵌套对象(而不是数组)的解决方案,因此我自己编写了一个 :) 可以处理字符串和整数。

  function sortObjectProperties(obj, sortValue){
      var keysSorted = Object.keys(obj).sort(function(a,b){return obj[a][sortValue]-obj[b][sortValue]});
      var objSorted = {};
      for(var i = 0; i < keysSorted.length; i++){
          objSorted[keysSorted[i]] = obj[keysSorted[i]];
      }
      return objSorted;
    }

使用方法:

    /* sample object with unsorder properties, that we want to sort by 
    their "customValue" property */

    var objUnsorted = {
       prop1 : {
          customValue : 'ZZ'
       },
       prop2 : {
          customValue : 'AA'
       }
    }

    // call the function, passing object and property with it should be sorted out
    var objSorted = sortObjectProperties(objUnsorted, 'customValue');

    // now console.log(objSorted) will return:
    { 
       prop2 : {
          customValue : 'AA'
       },
       prop1 : {
          customValue : 'ZZ'
       } 
    }

keysSorted按sortValue的升序排序,但作为JavaScript对象,它是一个无序属性集合,因此尝试对这些属性进行排序是没有意义的。 - Olivier

0

我已经按照自己的方式尝试过了

var maxSpeed = {
  car: 300, 
  bike: 60, 
  motorbike: 200, 
  airplane: 1000,
  helicopter: 400, 
  rocket: 8 * 60 * 60
};
var sorted = {}
 Object.keys(maxSpeed).sort ((a,b) => maxSpeed[a] - maxSpeed[b]).map(item => sorted[item] = maxSpeed[item]);
console.log(sorted)

0

感谢并继续回答@Nosredna

现在我们明白了对象需要转换为数组,然后对数组进行排序。这对于按字符串排序数组(或转换为数组的对象)非常有用:

Object {6: Object, 7: Object, 8: Object, 9: Object, 10: Object, 11: Object, 12: Object}
   6: Object
   id: "6"
   name: "PhD"
   obe_service_type_id: "2"
   __proto__: Object
   7: Object
   id: "7"
   name: "BVC (BPTC)"
   obe_service_type_id: "2"
   __proto__: Object


    //Sort options
    var sortable = [];
    for (var vehicle in options)
    sortable.push([vehicle, options[vehicle]]);
    sortable.sort(function(a, b) {
        return a[1].name < b[1].name ? -1 : 1;
    });


    //sortable => prints  
[Array[2], Array[2], Array[2], Array[2], Array[2], Array[2], Array[2]]
    0: Array[2]
    0: "11"
    1: Object
        id: "11"
        name: "AS/A2"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2
        __proto__: Array[0]
    1: Array[2]
    0: "7"
    1: Object
        id: "7"
        name: "BVC (BPTC)"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2

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