Sorting a converted object (Object.entries)

I have a large object of key:value pairs to sort by the value.
15

I am trying to convert to an array using Object.entries, I believe it results in an array of arrays (rather than an array of objects) so I am trying access the value by using index 1, rather than dot notation:

sortBy = () => {
    const countries = this.props.countriesToRender;
    const countriesArray = Object.entries(countries);
    return countriesArray.sort((a, b) => {
      return b[1] - a[1];
    });
  };

so far it doesn’t work, does this seem the right approach?

One possible way is the following:

sortBy = () => {
  const countries = this.props.countriesToRender;
  const countriesArray = Object
    .keys(countries)
    .map(country => ({ [country]: countries[country] }));

  return countriesArray.sort((a, b) => {
    const aVal = Object.values(a)[0];
    const bVal = Object.values(b)[0];
    return bVal - aVal;
  }); 
}

It will return an array of objects that looks something like:

[
  { Algeria: 2},
  { Albania: 8 },
  { Afghanistan: 3 }
  .
  .
  .
]

You did not specify what you wanted the objects inside the array to look like, but I assumed the above would work.

const countries = {
  Bfghanistan: 3,
  Zlbania: 9,
  Clgeria: 3
};

const arrOfArrays = Object.entries(countries);

const sorted = arrOfArrays.sort((a, b) => {
	return a[0].localeCompare(b[0]);
});

console.log(sorted);

I’m not entirely sure return val1 - val2 works. I think sort requires a return of -1, 1, 0.

https://jsfiddle.net/5Ldnt4h7/

Yes, that is exactly how I’d like them to look - thanks!
I’ll try it now, but also think I might need to set state so the sorted array is rendered? Will try it out :slight_smile:

@kerafyrm02 The bVal - aVal will work because it is a number and not a string.

Also, the OP mentioned wanted an array of objects and not an array of arrays which yours produces. However, it may be that is fine with the OP.

I actually want to sort by the numbers not the names, so will do [1] – using [0] will sort by the names I assume? Will try it.

Oh he’s sorting by the numbers and not sorting the country names alphabetically?

Yes, he wants the countries sorted in descending order by the value and not the name.

My solution does this.

import React from "react";

class Table extends React.Component {
  
  getCountryNames = () => {
    return Object.keys(this.props.countriesToRender);
  };

  getDeveloperCounts = () => {
    return Object.values(this.props.countriesToRender);
  };

  sortBy = () => {
    const countries = this.props.countriesToRender;
    const countriesArray = Object.keys(countries).map(country => ({
      [country]: countries[country]
    }));

    return countriesArray.sort((a, b) => {
      const aVal = Object.values(a)[0];
      const bVal = Object.values(b)[0];
      return bVal - aVal;
    });
  };

  render() {
    return (
      <div>
        <table className="ui celled center aligned table">
          <thead>
            <tr>
              <th>Country</th>
              <th>
                {" "}
                <button onClick={() => this.sortBy()}>Developers</button>
              </th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                {this.getCountryNames().map(name => {
                  return <tr>{name}</tr>;
                })}
              </td>
   
              <td>
                {this.getDeveloperCounts().map(count => {
                  return <tr>{count}</tr>;
                })}
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}
export default Table;

This is the whole component, I think I’m not feeding the results of the sort into the render properly.

Shouldn’t you be setting state of developers inside your method sortBy method?

no errors related to the sort

No because developers is the raw data, the developerCount is calculated from the countriesToRender method

I just tried adding a new state property, with sortBy as a callback to App.js but it didn’t make much difference

Where exactly are you wanting to show this array of objects in some way? Which component?

Gotcha. My error then.

Of course I had to find another way. :smiley:

const countries = {
  Bfghanistan: 2,
  Zlbania: 9,
  Clgeria: 3
};

const sorted = Object.entries(countries).sort(([c1, v1], [c2, v2]) => {
	return v2 - v1;
}).reduce((o, [k, v]) => (o[k] = v, o), {});

console.log(sorted);

in the Table.js .

I’ve moved it back up to App.js with a setState

  sortBy = () => {
    const countries = this.state.countriesToRender;
    const countriesArray = Object.keys(countries).map(country => ({
      [country]: countries[country]
    }));

    const sortedCountries = countriesArray.sort((a, b) => {
      const aVal = Object.values(a)[0];
      const bVal = Object.values(b)[0];
      return bVal - aVal;
    });
    this.setState({ countriesToRender: sortedCountries });
  };

While that works, I am not sure it is very readable.

1 Like

Yeah. Not really readable at all. lol.