1

I want to change the sequence of the keys of the object to the given one.(first male, then children followed by femal) There is an object:

const types = [
    {female: 100, male: 200, children: 150},
    {female: 100, male: 200, children: 150}
];

I get the object from the backend, where I need to change a sequence of the keys at the Front end of my app to male, children, female. I have never come across this problem, I tried several methods, didn't succeed. I will be extremely grateful for any help. Example output code for object fields:

{types && (
  <ul>_.map(Object.keys(types), key => (
    <li key={_.uniqueId(`${key}`)}>
      <span>{key, types[key]}</span>
    </li>
  </ul>
)}

100 female
200 male
150 children

The conclusion looks like this. It is necessary to change to:

200 male
150 children
100 female

Thank you very much!

Ankit Kumar Ojha
  • 2,296
  • 2
  • 22
  • 30
  • `Object.keys` returns an array in which you can use a `sort` method based on your desires. – Jankapunkt Sep 13 '18 at 07:09
  • Could you please explain what you're trying to do and why it matters? As per the spec, property order on an object is not guaranteed. You'd have to use something to compare to containing the correct order, like an array ['male', 'children','female']` or a map with the same key/values, since those two do have guaranteed order. – Shilly Sep 13 '18 at 07:09
  • Possible duplicate of [Does ES6 introduce a well-defined order of enumeration for object properties?](https://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties) – str Sep 13 '18 at 07:09
  • @Shilly order is so important to output on page, on backend I have incorrect order which I need to change. Yes, I read about it, but I cant realize :( – Kirill Oleynik Sep 13 '18 at 07:15
  • In my own code, having to rely on property order was usually a sign of me trying to abstract things that should not be abstracted. So to guarantee order, I write out the templates in that specific order instead of looping over an object. Or I provide an array with the correct order and loop that array instead of looping the objects keys. Imho, the order of which keys are defined on an object should never matter for the correct functioning of an app. – Shilly Sep 13 '18 at 07:17

4 Answers4

2

You can use JSON.stringify(value[, replacer[, space]]) to format string and again convert in json

const types = [
    {female: 100, male: 200, children: 150},
    {female: 100, male: 200, children: 150}
];

var newjson = JSON.parse(JSON.stringify( types , ["male","female","children"]));
console.log(newjson);
Manasi
  • 765
  • 6
  • 17
  • I must say it's a smart solution, but I'm little skeptical about the performance here. JSON.parse and JSON.stringify are unpopular because of their performance. – Ankit Kumar Ojha Sep 13 '18 at 07:19
0

You might want to use Map, instead of objects to store the data from backend. JS Objects does not guarantee the order of keys (it's unordered). Even though JS engines implementation have ICs, which can make you delude that order never changes. I have quoted the ECMA Script 3rd edition below which will make it even more clearer.

4.3.3 Object: An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

Since ECMAScript 2015, using the Map object could be an alternative. A Map shares some similarities with an Object and guarantees the keys order:

A Map iterates its elements in insertion order, whereas iteration order is not specified for Objects.

Ankit Kumar Ojha
  • 2,296
  • 2
  • 22
  • 30
0

I think it would be really bad idea to rely on the order of the object properties. Since it is an object coming from the backend using a Map is not going to solve your problems.

The easiest is probably to have an array with the property names in the order you want to display them. It gives you all the flexibility you will need and removes the reliances on order from an object.

const 
  data = [
    {female: 100, male: 200, children: 150},
    {female: 101, male: 201, children: 151}
  ],
  // This array controls the order the data item properties
  // will be added to the DOM.
  displayOrder = ['male', 'female', 'children'];

/**
 * Returns a string with the values of the provided item
 * wrapped in markup for TD elements.
 */ 
function createItemCells(item) {
  // Iterate of the properties to display in the table, this ensures
  // they'll be added in the desired order.
  return displayOrder.reduce((result, key) => {
    // Append a TD element for the current item property.
    return result + `<td>${item[key]}</td>`;
  }, '');
}

const
  // Iterate over the items in the data array and create a string
  // per item to show the data in the table.
  rows = data.reduce((output, item) => {  
    // Append a new row to the output.
    return output + `<tr>${ createItemCells(item) }</tr>`;
  }, '');
  
// Insert the generated rows into the table body in the DOM.
document.getElementById('output').innerHTML = rows;
<table>
  <thead>
    <tr>
      <th>Male</th>
      <th>Female</th>
      <th>Children</th>
    </tr>
  </thead>
  <tbody id="output"></tbody>
</table>
Thijs
  • 2,341
  • 2
  • 14
  • 22
0

Situation: We need to display properties and values of an object inside a HTML list in a specific order.

Problems:

1) Property order is not 100% guaranteed, depends on engine implementation.

2) The data comes from the backend in JSON format, so we don't have a way to represent complex objects like a Map, since JSON does not know what maps are.

Solutions:

1) Write out the template fully:

const types = [
  {female: 100, male: 200, children: 150},
  {female: 100, male: 200, children: 150}
];
const html = [
  '<ul>',
  ...types.map( item => `<li>${ item.male } male<\/li><li>${ item.children } children<\/li><li>${ item.female } female<\/li>` ),
  '</ul>'
].join( '' );
console.log( html );

2) Provide an array containing the correct order to loop:

const types = [
  {female: 100, male: 200, children: 150},
  {female: 100, male: 200, children: 150}
];
const proper_order = [ 'male', 'children', 'female' ];
const create_html = function( data, order ) {
  return [
    '<ul>',
    ...types.map( item => order.map( property_name => `<li>${ item[ property_name ] } ${ property_name }<\/li>` ).join( '' )),
    '</ul>'
  ].join( '' );
};
const html = create_html( types, proper_order );
console.log( html );

Disclaimer: I'm using the array.join(''); method to create the html strings as an example only. A proper templating engine is adviced. The same logic is still applicable.

Shilly
  • 8,511
  • 1
  • 18
  • 24