0

Initially, I have such an object

There is more data in it, I missed it

"Citizens": [

            {
                "_id": "6070be28c98d5a0ea88f131c",
                "id": 1,
                "name": "Karl",
                "city_id": "1",
                "groups": []
            },
          ]

After passing through it in this cycle

                       for(let i = 0; i < objTmp[0]["Citizens"].length; i++){
                            for(let j = 0; j < citiesAll[0]["Cities"].length; j++){
                                if(objTmp[0]["Citizens"][i].id == citiesAll[0]["Cities"][j].id) {

           
                                  objTmp[0]["Citizens"][i].city = citiesAll[0]["Cities"][j];


                                }       
                            }
                        }

I add a city object from another object to it

I get such an object

"Citizens": [

        {
            "city": {
                "id": 1,
                "name": "Moscow",
                "data": "10000000"
            },
            "_id": "6070be28c98d5a0ea88f131c",
            "id": 1,
            "name": "Karl",
            "city_id": "1",
            "groups": []
        },

]

Question?

How can I add city not to the beginning, as shown here, but to the end?

Cooler-cpu
  • 31
  • 1
  • 7
  • Object properties don't have an order. It's not like an array. –  Apr 09 '21 at 21:13
  • They do have an order, though it is not always enforced. see: [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) – pilchard Apr 09 '21 at 21:15
  • objects is really out of order, but there must be a way to add city to the end? – Cooler-cpu Apr 09 '21 at 21:16
  • 1
    There is not a way to add it to the end. It's the same object, regardless if the city is in the beginning or the end or the middle. –  Apr 09 '21 at 21:18
  • Working on a solution now. Stay tuned... – Brandon McConnell Apr 09 '21 at 21:46
  • @Brandon McConnell, thanks expect – Cooler-cpu Apr 09 '21 at 22:23
  • Posted my fully explanation and examples. Please consider accepting my answer if this answers your question and works for you – Brandon McConnell Apr 09 '21 at 22:30
  • @Brandon McConnell, Thank you very cool – Cooler-cpu Apr 09 '21 at 22:34
  • @ Brandon McConnell How to make this construct work in nested loops? – Cooler-cpu Apr 09 '21 at 22:54
  • @ Brandon McConnell the code does not work because citiesAll [0] ["Cities"] has many objects – Cooler-cpu Apr 09 '21 at 23:11
  • @Cooler-cpu could you post the entire code for both objects? My solutions do use nested loops, just nested array method loops. I'll add examples for both of my solutions using classic and `for..of` loops as well. I just need the full data for both objects you're using. – Brandon McConnell Apr 10 '21 at 12:12

2 Answers2

1

As Roshan mentioned, key orders aren't reliable in JS and really shouldn't be relied upon. If you need to maintain key order, I suggest using a map.

Here are examples of all both (including the unreliable object route):

1. As an Object

Because object keys have no inherent order, this may not look correct if you run it in your browser console and expand your object, but if you run the snippet below, you'll see the correct, expected order in your console. To ensure the desired order, use a map, explained further down in section 2.

1.1. As an Object using nested array-method loops

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

objTmp[0]["Citizens"].forEach((citizen, i) => citiesAll[0]["Cities"].find(city => city.id && citizen.id && city.id === citizen.id && (objTmp[0]["Citizens"][i] = { ...citizen, city: { ...city } } )))

console.log(objTmp[0]["Citizens"][0]);

1.2. As an Object using nested for loops

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

for (let i = 0; i < objTmp[0]["Citizens"].length; i++) {
    for (let j = 0; j < citiesAll[0]["Cities"].length; j++) {
        if (objTmp[0]["Citizens"][i].id && citiesAll[0]["Cities"][j].id && objTmp[0]["Citizens"][i].id === citiesAll[0]["Cities"][j].id) {
            objTmp[0]["Citizens"][i] = { ...objTmp[0]["Citizens"][i], city: { ...citiesAll[0]["Cities"][j] } };
            break;
        }
    }
}

console.log(objTmp[0]["Citizens"][0]);

1.3. As an Object using nested for..of loops

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

{
    let i = 0;
    for (citizen of objTmp[0]["Citizens"]) {
        let j = 0;
        for (city of citiesAll[0]["Cities"]) {
            if (city.id && citizen.id && city.id === citizen.id) {
                objTmp[0]["Citizens"][i] = { ...citizen, city: { ...city } };
                break;
            }
            j++;
        }
        i++;
    }
}

console.log(objTmp[0]["Citizens"][0]);

2. As a Map

This one you'll need to run in your browser's console since StackOverflow's console cannot print JS Map data.

2.1. As a Map using nested array-method loops

// I am only using this replacer function to support logging the result Map data to the console properly. This function is not require for production-use.
const replacer = (a,e) => e instanceof Map?{dataType:"Map",value:Array.from(e.entries())}:e;

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

objTmp[0]["Citizens"].forEach((citizen, i) => (objTmp[0]["Citizens"][i] = new Map(Object.entries(citizen)), citiesAll[0]["Cities"].find(city => city.id && objTmp[0]["Citizens"][i].get('id') && city.id === objTmp[0]["Citizens"][i].get('id') && (objTmp[0]["Citizens"][i].set('city', { ...city })))));

console.log(JSON.stringify(objTmp[0]["Citizens"][0], replacer, 2));

2.2. As a Map using nested for loops

// I am only using this replacer function to support logging the result Map data to the console properly. This function is not require for production-use.
const replacer = (a,e) => e instanceof Map?{dataType:"Map",value:Array.from(e.entries())}:e;

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

for (let i = 0; i < objTmp[0]["Citizens"].length; i++) {
    objTmp[0]["Citizens"][i] = new Map(Object.entries(objTmp[0]["Citizens"][i]));
    for (let j = 0; j < citiesAll[0]["Cities"].length; j++) {
        if (citiesAll[0]["Cities"][j].id && objTmp[0]["Citizens"][i].get('id') && citiesAll[0]["Cities"][j].id === objTmp[0]["Citizens"][i].get('id')) {
            objTmp[0]["Citizens"][i].set('city', { ...citiesAll[0]["Cities"][j] });
            break;
        }
    }
}

console.log(JSON.stringify(objTmp[0]["Citizens"][0], replacer, 2));

2.3. As a Map using nested for..of loops

// I am only using this replacer function to support logging the result Map data to the console properly. This function is not require for production-use.
const replacer = (a,e) => e instanceof Map?{dataType:"Map",value:Array.from(e.entries())}:e;

const objTmp = [{ Citizens: [{ _id: "6070be28c98d5a0ea88f131c", id: 1, name: "Karl", city_id: "1", groups: [] }]}];
const citiesAll = [{ Cities: [{ id: 1, name: "Moscow", data: "10000000" }]}];

{
    let i = 0;
    for (citizen of objTmp[0]["Citizens"]) {
        objTmp[0]["Citizens"][i] = new Map(Object.entries(citizen));
        let j = 0;
        for (city of citiesAll[0]["Cities"]) {
            if (city.id && objTmp[0]["Citizens"][i].get('id') && city.id === objTmp[0]["Citizens"][i].get('id')) {
                objTmp[0]["Citizens"][i].set('city', { ...city });
                break;
            }
            j++;
        }
        i++;
    }
}

console.log(JSON.stringify(objTmp[0]["Citizens"][0], replacer, 2));
Brandon McConnell
  • 5,776
  • 1
  • 20
  • 36
  • How to make this construct work in nested loops? – Cooler-cpu Apr 09 '21 at 22:53
  • @Cooler-cpu I've updated my solution to include examples of classic `for` loops and `for..of` loops in addition to the array `forEach()` method loops. Please review and try each. Keep in mind that maps will retain order reliably, while objects will not. In order to test the Map solutions (2.1, 2.2, and 2.2), you will need to run the code in your console, since StackOverflow's does not currently support logging map data to its built-in console. – Brandon McConnell Apr 11 '21 at 22:18
0

I have to disagree with the other answer(s) providing methods of ordering object keys.

My answer: don't do that. Attempting to order the keys of a JavaScript object is poor practice and is anti-semantic. People reading your code either will be confused or will rightly assume it's full of bugs.

I fully recognize that the keys will have a de-facto order but I'm offering the opinion that you shouldn't rely on it.

Use maps or tuples or something else built to have an ordering.

Chris
  • 6,805
  • 3
  • 35
  • 50
  • My answer is the only other answer at this point, and I specifically said not to re-order Object keys and to use a Map instead, which I provided specific guidelines and examples, so I'm not sure which other answer(s) you're referring to. – Brandon McConnell Apr 11 '21 at 22:29