Sort array of objects


#1

Hi all ! Could anyone suggest please, how sort array of objects ? I am trying like this but function dose not run … What I did wrong ? I did not see …

            console.log("aaaaaaaa",a);
            console.log("bbbbbbbb",b);
ShowModelsList():Promise<any> {

    return new Promise ((resolve,reject)=>{
      this.models = [];
      let tmpModel = [];

      this.modelsService.getTotalRows(this.sid).then(data => {

        this.total = data.res.rows.item(0)["count(*)"];

        if (this.total > this.record) {
          this.offset = this.record;
          this.total -= this.record;
          this.hasMoreData = true;
        } else {
          this.offset = this.total;
          this.hasMoreData = false;
        }
        this.modelsService.getLimitData(this.sid, this.limit, this.offset).then(data=> {

          for (let i = 0; i < data.res.rows.length; i++) {
            this.checkModelFileExist(data.res.rows.item(i).external_id).then(ModelFileExistResult=>{
              this.models.push(Object.assign({modelfileexist: ModelFileExistResult},data.res.rows.item(i)));

              let obj = Object.assign({modelfileexist: ModelFileExistResult},data.res.rows.item(i));
              tmpModel.push(obj);

            }).catch(err=>{
              console.warn(err);
            });

          }


          console.log("tmpModel",tmpModel);

          Array.prototype.sort.call(tmpModel, function (a, b) {

            console.log("aaaaaaaa",a);
            console.log("bbbbbbbb",b);


            if (a.external_id > b.external_id) {
              return 1;
            }
            if (a.external_id < b.external_id) {
              return -1;
            }

            return 0;

          });

          console.log("tmpModel",tmpModel);


        }).then(() =>{

        });

        this.limit = this.offset;
      }).catch(err=>{
        console.warn(err);
      })
    });
  }

#2

I do not understand why tmpModel or this.models dose not working (not sorting) but if I create custom array of object before Array.prototype.sort.call it will work …


#3

You’re using futures (i.e. Promises) in the for loop, which means that your array isn’t constructed by the time that you hit the call to sort.

You need to wait for all the for loop promises to finish first, probably by constructing an array and then using Promise.All. Then you can sort your array.


#4

SigmundFroyd, good day ! Could you show little example ?


#5

You see both calls of
console.log("tmpModel",tmpModel);
right? If not, then maybe your promises are the reason


#6

@SigmundFroyd already solved this, but I want to reiterate a couple of pet peeves:

  • do not explicitly instantiate Promises
  • do not (ab)use any

#7

rapropos, SigmundFroyd, thanks for answer. I will try !


#8

rapropos, Could I resolve tmpModel and then sort ? Like …

ShowModelsList().then(data => {

          Array.prototype.sort.call(data, function (a, b) {
            if (a.external_id > b.external_id) {
              return 1;
            }
            if (a.external_id < b.external_id) {
              return -1;
            }
            return 0;
          });
});

#9

Theoretically, but not the way you’re doing it now. Follow @SigmundFroyd’s advice, build an array of Promises consisting of all the actions needed for each element going into the list of models, and use Promise.all to wait until they have all completed before you can consider tmpModel built.


#10

This is the general idea:

this.modelsService.getLimitData(this.sid, this.limit, this.offset).then(data=> {
    let promises = Promise<boolean>[];
    
    for (let i = 0; i < data.res.rows.length; i++) {
        promises.push(this.checkModelFileExist(data.res.rows.item(i).external_id).then(ModelFileExistResult=>{
          this.models.push(Object.assign({modelfileexist: ModelFileExistResult},data.res.rows.item(i)));

          let obj = Object.assign({modelfileexist: ModelFileExistResult},data.res.rows.item(i));
          tmpModel.push(obj);

          return true;
        }).catch(err=>{
          console.warn(err);
        }));
    }

    return Promise.all(promises);
}
.then(_ => {
    console.log("tmpModel", tmpModel);
    
    tmpModel.sort((a, b) => {
        console.log("aaaaaaaa",a);
        console.log("bbbbbbbb",b);

        if (a.external_id > b.external_id) {
          return 1;
        }
        if (a.external_id < b.external_id) {
          return -1;
        }

        return 0;
    });

    console.log("tmpModel",tmpModel);
})

#11

That loop with all the pushing is kinda clunky. I get that it has to be written that way because you have to keep calling item(), but it sure would be nifty if there was some way to do it with Array.map().


#12

Agreed. I’ve never understood the decision to have the API have an item function rather than just being an array. In one of my projects I wound up just creating a wrapper in order to be able to use Array.map(). It was a great decision.


#13

Literally everything I know about Firebase I have learned from seeing people post problematic code here, but I would assume it’s for efficiency, so that one can choose only to fetch certain items without incurring the overhead for fetching all of them up front.


#14

SigmundFroyd, I try but app dose not build … I see error …

Operator '>' cannot be applied to types 'boolean' and 'undefined[]'.

I am trying example higher … it dose not working for me … It dose not solved problem … it return one object ((