Steerpike
Steerpike

Reputation: 17544

Sorting object property by values

If I have a JavaScript object such as:

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

Is there a way to sort the properties based on value? So that I end up with

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

Upvotes: 1035

Views: 1563120

Answers (30)

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20080

we can sort value using sort() and Object.entries() method in the following way

var list = {
"10": "5",
"11": "3",
"12": "3",
"13": "3",
"14": "3",
"15": "4",
"16": "3",
"17": "4",
"18": "4",
"19": "3",
"20": "3",
"21": "3",
"22": "3",
"23": "3",
"24": "3",
"25": "4",
"26": "3",
"27": "3",
"28": "4",
"29": "4",
"30": "5",
"31": "5",
"32": "4",
"33": "4",
"37": "1",
"38": "1",
"39": "4",
"40": "1",
"41": "3",
"42": "4",
"43": "4",
"44": "2",
"45": "4",
"46": "1",
"47": "1",
"48": "1",
"49": "1",
"50": "1",
"51": "1",
"52": "1",
"53": "1",
"54": "1",
"55": "1",
"56": "1",
"57": "1",
"58": "1",
"59": "1",
"60": "3",
"61": "3",
"64": "3",
"65": "3",
"66": "3",
"67": "1",
"69": "3",
"71": "3",
"72": "4",
"73": "3",
"74": "3",
"90": "1",
"95": "1",
"null": "1",
"02": "1",
"03": "1",
"04": "1",
"05": "3",
"06": "3",
"07": "3",
"09": "3",
"1A": "5",
"1B": "3",
"1C": "3",
"1D": "3",
"1E": "4",
"1H": "1",
"6A": "1",
"2A": "1",
"2B": "3",
"2C": "3",
"2D": "3",
"2E": "3",
"2F": "5",
"2G": "3",
"2H": "3",
"2J": "3",
"2K": "4",
"2L": "4",
"2M": "4",
"2N": "3",
"2P": "3",
"2Q": "3",
"2R": "5"
};

console.log(Object.entries(list).sort().map(m => m.at())); // only value
console.log(Object.entries(list).sort()); // key and value

Upvotes: 0

Nosredna
Nosredna

Reputation: 86186

Move them to an array, sort that array, and then use that array for your purposes. Here's a solution:

let maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};
let sortable = [];
for (var vehicle in maxSpeed) {
    sortable.push([vehicle, maxSpeed[vehicle]]);
}

sortable.sort(function(a, b) {
    return a[1] - b[1];
});

// [["bike", 60], ["motorbike", 200], ["car", 300],
// ["helicopter", 400], ["airplane", 1000], ["rocket", 28800]]

Once you have the array, you could rebuild the object from the array in the order you like, thus achieving exactly what you set out to do. That would work in all the browsers I know of, but it would be dependent on an implementation quirk, and could break at any time. You should never make assumptions about the order of elements in a JavaScript object.

let objSorted = {}
sortable.forEach(function(item){
    objSorted[item[0]]=item[1]
})

In ES8, you can use Object.entries() to convert the object into an array:

const maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};

const sortable = Object.entries(maxSpeed)
    .sort(([,a],[,b]) => a-b)
    .reduce((r, [k, v]) => ({ ...r, [k]: v }), {});

console.log(sortable);


In ES10, you can use Object.fromEntries() to convert array to object. Then the code can be simplified to this:

const maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};

const sortable = Object.fromEntries(
    Object.entries(maxSpeed).sort(([,a],[,b]) => a-b)
);

console.log(sortable);

Upvotes: 1147

Ali Zain UL Yasoob
Ali Zain UL Yasoob

Reputation: 117

Here's another way to achieve this

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

const sortedByValue = Object.fromEntries(
  Object.entries(list).sort((a, b) => {
    return a[1] - b[1];
  })
);

console.log(sortedByValue);

Upvotes: 4

Below is the working code

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

// convert the list to array of key and value pair
for(let  i in list){
    sortArray.push({key : i, value:list[i]});
}

//console.log(sortArray);
// sort the array using value.
sortArray.sort(function(a,b){
return a.value - b.value;
});

//console.log(sortArray);

// now create a newList of required format.
let newList={};
for(let i in sortArray){
newList[sortArray[i].key] = sortArray[i].value;
}

console.log(newList);

Upvotes: -2

Stano
Stano

Reputation: 8939

For completeness sake, this function returns sorted array of object properties:

function sortObject(obj) {
    var arr = [];
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            arr.push({
                'key': prop,
                'value': obj[prop]
            });
        }
    }
    arr.sort(function(a, b) { return a.value - b.value; });
    //arr.sort(function(a, b) { return a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings
    return arr; // returns array
}

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var arr = sortObject(list);
console.log(arr); // [{key:"bar", value:15}, {key:"me", value:75}, {key:"you", value:100}, {key:"foo", value:116}]

JSFiddle with the code above is here. This solution is based on this article.

Updated fiddle for sorting strings is here. You can remove both additional .toLowerCase() conversions from it for case sensitive string comparation.

Upvotes: 72

Roman Yudin
Roman Yudin

Reputation: 973

Underscore.js or Lodash.js for advanced array or object sorts

var data = {
  "models": {

    "LTI": [
      "TX"
    ],
    "Carado": [
      "A",
      "T",
      "A(пасс)",
      "A(груз)",
      "T(пасс)",
      "T(груз)",
      "A",
      "T"
    ],
    "SPARK": [
      "SP110C 2",
      "sp150r 18"
    ],
    "Autobianchi": [
      "A112"
    ]
  }
};

var arr = [],
  obj = {};
for (var i in data.models) {
  arr.push([i, _.sortBy(data.models[i], function(el) {
    return el;
  })]);
}
arr = _.sortBy(arr, function(el) {
  return el[0];
});
_.map(arr, function(el) {
  return obj[el[0]] = el[1];
});
console.log(obj);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js" integrity="sha256-qXBd/EfAdjOA2FGrGAG+b3YBn2tn5A6bhz+LSgYD96k=" crossorigin="anonymous"></script>

Upvotes: 8

simon
simon

Reputation: 944

A follow up answer to a long outdated question. I wrote two functions, one in which it sorts by keys, and the other by values, and returns the object in its sorted form in both functions. It should also work on strings as that is the reason why I am posting this (was having difficulty with some of the above on sorting by values if the values weren't numeric).

const a = {
    absolutely: "works",
    entirely: 'zen',
    best: 'player',
    average: 'joe'
}


const prop_sort = obj => {
    return Object.keys(obj)
        .sort()
        .reduce((a, v) => {
            a[v] = obj[v];
            return a; 
        }, {});
}

const value_sort = obj => {
    const ret = {}
    Object.values(obj)
        .sort()
        .forEach(val => {
            const key = Object.keys(obj).find(key => obj[key] == val)
            ret[key] = val
        })
    return ret
}

console.log(prop_sort(a))
console.log(value_sort(a))

Upvotes: 2

Syed ss
Syed ss

Reputation: 19

I have tried in my own way

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)

Upvotes: 0

index
index

Reputation: 41

Another example with Object.values, sort() and the spread operator.

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'
    }
}

We transform the object into an array of objects with Object.values:

var toArray = Object.values(paintings)

Then we sort the array (by year and by price), using the spread operator to make the original array inmutable and the sort() method to sort the array:

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

Finally, we generate the new sorted objects (again, with the spread operator to keep the original form of object of objects with a [x: number] as key):

var paintingsSortedByYear = {
    ...sortedByYear
}

var paintingsSortedByPrice = {
    ...sortedByPrice
}

Hope this could be helpful!

Upvotes: 2

Jason Joseph Nathan
Jason Joseph Nathan

Reputation: 7601

An "arrowed" version of @marcusR 's answer for reference

var myObj = { you: 100, me: 75, foo: 116, bar: 15 };
keysSorted = Object.keys(myObj).sort((a, b) => myObj[a] - myObj[b]);
alert(keysSorted); // bar,me,you,foo

UPDATE: April 2017 This returns a sorted myObj object defined above.

const myObj = { you: 100, me: 75, foo: 116, bar: 15 };
const result =
  Object.keys(myObj)
    .sort((a, b) => myObj[a] - myObj[b])
    .reduce(
      (_sortedObj, key) => ({
        ..._sortedObj,
        [key]: myObj[key]
      }),
      {}
    );
document.write(JSON.stringify(result));

UPDATE: March 2021 - Object.entries with sort function (updated as per comments)

const myObj = { you: 100, me: 75, foo: 116, bar: 15 };
const result = Object
 .entries(myObj)
 .sort((a, b) => a[1] - b[1])
 .reduce((_sortedObj, [k,v]) => ({
   ..._sortedObj, 
   [k]: v
 }), {})
document.write(JSON.stringify(result));

Upvotes: 64

Sorting object property by values

const obj = { you: 100, me: 75, foo: 116, bar: 15 };
const keysSorted = Object.keys(obj).sort((a, b) => obj[a] - obj[b]);
const result = {};
keysSorted.forEach(key => { result[key] = obj[key]; });
document.write('Result: ' + JSON.stringify(result));

The desired output:

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

References:

Upvotes: 4

VenkateshMogili
VenkateshMogili

Reputation: 701

Thanks to @orad for providing the answer in TypeScript. Now, We can use the below codesnippet in JavaScript.

function sort(obj,valSelector) {
  const sortedEntries = Object.entries(obj)
    .sort((a, b) =>
      valSelector(a[1]) > valSelector(b[1]) ? 1 :
      valSelector(a[1]) < valSelector(b[1]) ? -1 : 0);
  return new Map(sortedEntries);
}

const Countries = { "AD": { "name": "Andorra", }, "AE": { "name": "United Arab Emirates", }, "IN": { "name": "India", }} 

// Sort the object inside object. 
var sortedMap = sort(Countries, val => val.name); 
// Convert to object. 
var sortedObj = {}; 
sortedMap.forEach((v,k) => { sortedObj[k] = v }); console.log(sortedObj); 

//Output: {"AD": {"name": "Andorra"},"IN": {"name": "India"},"AE": {"name": "United Arab Emirates"}}

Upvotes: 5

kiding
kiding

Reputation: 1925

ECMAScript 2017 introduces Object.values / Object.entries. As the name suggests, the former aggregates all the values of an object into an array, and the latter does the whole object into an array of [key, value] arrays; Python's equivalent of dict.values() and dict.items().

The features make it pretty easier to sort any hash into an ordered object. As of now, only a small portion of JavaScript platforms support them, but you can try it on Firefox 47+.

EDIT: Now supported by all modern browsers!

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

let entries = Object.entries(obj);
// [["you",100],["me",75],["foo",116],["bar",15]]

let sorted = entries.sort((a, b) => a[1] - b[1]);
// [["bar",15],["me",75],["you",100],["foo",116]]

Upvotes: 162

Vignesh G
Vignesh G

Reputation: 151

To find frequency of each element and sort it by frequency/values.

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);

Outputs:

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

Upvotes: 1

Jasp402
Jasp402

Reputation: 412

There are many ways to do this, but since I didn't see any using reduce() I put it here. Maybe it seems utils to someone.

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

let result = Object.keys(list).sort((a,b)=>list[a]>list[b]?1:-1).reduce((a,b)=> {a[b]=list[b]; return a},{});

console.log(result);

Upvotes: 4

Chirag Modi
Chirag Modi

Reputation: 31

<pre>
function sortObjectByVal(obj){  
var keysSorted = Object.keys(obj).sort(function(a,b){return obj[b]-obj[a]});
var newObj = {};
for(var x of keysSorted){
    newObj[x] = obj[x];
}
return newObj;

}
var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
console.log(sortObjectByVal(list));
</pre>

Upvotes: 3

Ivan Bozveliev
Ivan Bozveliev

Reputation: 11

my solution with sort :

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

let sorted = Object.entries(list).sort((a,b) => a[1] - b[1]);

for(let element of sorted) {
    console.log(element[0]+ ": " + element[1]);
}

Upvotes: 1

Remi Prasanna
Remi Prasanna

Reputation: 51

let toSort = {a:2323, b: 14, c: 799} 
let sorted = Object.entries(toSort ).sort((a,b)=> a[1]-b[1]) 

Output:

[ [ "b", 14 ], [ "c", 799 ], [ "a", 2323 ] ]

Upvotes: 4

Oleg
Oleg

Reputation: 1140

const arrayOfObjects = [
{name: 'test'},
{name: 'test2'}
]

const order = ['test2', 'test']

const setOrder = (arrayOfObjects, order) =>
    arrayOfObjects.sort((a, b) => {
        if (order.findIndex((i) => i === a.name) < order.findIndex((i) => i === b.name)) {
            return -1;
        }

        if (order.findIndex((i) => i === a.name) > order.findIndex((i) => i === b.name)) {
            return 1;
        }

        return 0;
    });

Upvotes: 2

James T.
James T.

Reputation: 978

input is object, output is object, using lodash & js built-in lib, with descending or ascending option, and does not mutate input object

eg input & output

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

The implementation

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));

Upvotes: 1

orad
orad

Reputation: 16056

TypeScript

The following function sorts object by value or a property of the value. If you don't use TypeScript you can remove the type information to convert it to JavaScript.

/**
 * Represents an associative array of a same type.
 */
interface Dictionary<T> {
  [key: string]: T;
}

/**
 * Sorts an object (dictionary) by value or property of value and returns
 * the sorted result as a Map object to preserve the sort order.
 */
function sort<TValue>(
  obj: Dictionary<TValue>,
  valSelector: (val: TValue) => number | string,
) {
  const sortedEntries = Object.entries(obj)
    .sort((a, b) =>
      valSelector(a[1]) > valSelector(b[1]) ? 1 :
      valSelector(a[1]) < valSelector(b[1]) ? -1 : 0);
  return new Map(sortedEntries);
}

Usage

var list = {
  "one": { height: 100, weight: 15 },
  "two": { height: 75, weight: 12 },
  "three": { height: 116, weight: 9 },
  "four": { height: 15, weight: 10 },
};

var sortedMap = sort(list, val => val.height);

The order of keys in a JavaScript object are not guaranteed, so I'm sorting and returning the result as a Map object which preserves the sort order.

If you want to convert it back to Object, you can do this:

var sortedObj = {} as any;
sortedMap.forEach((v,k) => { sortedObj[k] = v });

Upvotes: 3

Maryam Koulaei
Maryam Koulaei

Reputation: 774

Very short and simple!

var sortedList = {};
Object.keys(list).sort((a,b) => list[a]-list[b]).forEach((key) => {
    sortedList[key] = list[key]; });

Upvotes: 9

daniil4udo
daniil4udo

Reputation: 101

Sort values without multiple for-loops (to sort by the keys change index in the sort callback to "0")

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

let sorted = Object.fromEntries(
                Object.entries(list).sort( (a,b) => a[1] - b[1] )    
             ) 
console.log('Sorted object: ', sorted) 

Upvotes: 9

Vasil Nikolov
Vasil Nikolov

Reputation: 1120

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

function sortAssocObject(list) {
    var sortable = [];
    for (var key in list) {
        sortable.push([key, list[key]]);
    }
    // [["you",100],["me",75],["foo",116],["bar",15]]

    sortable.sort(function(a, b) {
        return (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0));
    });
    // [["bar",15],["me",75],["you",100],["foo",116]]

    var orderedList = {};
    for (var idx in sortable) {
        orderedList[sortable[idx][0]] = sortable[idx][1];
    }

    return orderedList;
}

sortAssocObject(list);

// {bar: 15, me: 75, you: 100, foo: 116}

Upvotes: 10

Milad Aslani
Milad Aslani

Reputation: 21

    var list = {
    "you": 100,
    "me": 75,
    "foo": 116,
    "bar": 15
};
var tmpList = {};
while (Object.keys(list).length) {
    var key = Object.keys(list).reduce((a, b) => list[a] > list[b] ? a : b);
    tmpList[key] = list[key];
    delete list[key];
}
list = tmpList;
console.log(list); // { foo: 116, you: 100, me: 75, bar: 15 }

Upvotes: 2

esneyderp
esneyderp

Reputation: 111

Just in case, someone is looking for keeping the object (with keys and values), using the code reference by @Markus R and @James Moran comment, just use:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var newO = {};
Object.keys(list).sort(function(a,b){return list[a]-list[b]})
                 .map(key => newO[key] = list[key]);
console.log(newO);  // {bar: 15, me: 75, you: 100, foo: 116}

Upvotes: 3

Ankit Sinha
Ankit Sinha

Reputation: 1680

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 Link

Upvotes: 0

Kiran Debnath
Kiran Debnath

Reputation: 71

a = { b: 1, p: 8, c: 2, g: 1 }
Object.keys(a)
  .sort((c,b) => {
    return a[b]-a[c]
  })
  .reduce((acc, cur) => {
    let o = {}
    o[cur] = a[cur]
    acc.push(o)
    return acc
   } , [])

output = [ { p: 8 }, { c: 2 }, { b: 1 }, { g: 1 } ]

Upvotes: 2

Ashutosh Ranjan
Ashutosh Ranjan

Reputation: 642

here is the way to get sort the object and get sorted object in return

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

you can customise your sorting function as per your requirement

Upvotes: 1

Mahendra Kulkarni
Mahendra Kulkarni

Reputation: 1507

Here is one more example:

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);

Upvotes: 1

Related Questions