Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Web Development
  3. JavaScript
  4. Sorting an array in typescript, based on a search query

Sorting an array in typescript, based on a search query

Scheduled Pinned Locked Moved JavaScript
javascriptdesigndata-structurescsharphtml
8 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jkirkerx
    wrote on last edited by
    #1

    So I created this user interface to manage the sub categories of a category. I have the whole document loaded in Angular V7+ as a model, and I just list the sub categories in a table. Now I have a search interface in which I'd like to query to sub categories to find a specific one. In all my other uses of search, I call a service to .Net Core and let core find the answer and return them. Well that's easy because I'm loading documents. But this time I'd like to just search the model in the DOM. In other words find the data within the document. This way I can edit the document and return the whole document upon a change and let Core update it. So I can find the Sub Category, but I'd like to reorder the array. Show the search results first and then the rest in TypeScript. Right now I'm just loading the result in a Modal UI for editing. But I will run into this in the future so I should figure it out. Not sure if I'm approaching this right or not as far as my document design goes. Of if it's not feasible to do and I should write a service for it and let Core do the work. I looked at this [javascript - Reordering arrays - Stack Overflow](https://stackoverflow.com/questions/2440700/reordering-arrays). I can sort the list, and splice, but this is more complicated to me. By the way, result just returns 1 record even if 2 exists. eg.

    {
    "_id" : "5d702eab43c22b1674a8e680",
    "Name" : "SSD Drives",
    "Description" : "Solid State Hard Drives",
    "Image" : {
    "_id" : null,
    "Name" : null,
    "Alt" : null,
    "Data" : null,
    "Base64" : null,
    "Url" : null,
    "Type" : null
    },
    "CreatedBy" : "admin",
    "CreatedOn" : ISODate("2019-09-04T21:37:47.331Z"),
    "UpdatedOn" : ISODate("2019-09-06T16:58:16.464Z"),
    "Selected" : false,
    "SubCategories" : [
    {
    "_id" : "5d717a48675cc0229cf15ee5",
    "Name" : "SATA",
    "Description" : "2 1/2\" Sata 3 Drive",
    "CreatedBy" : "admin",
    "CreatedOn" : ISODate("2019-09-05T21:12:41.633Z"),
    "UpdatedOn" : ISODate("2019-09-05T21:12:18.721Z"),
    "Selected" : false
    },
    {
    "_id" : "5d717b54c4653d1c24753241",
    "Name" : "PCIe",
    "Description" : "PCI Addon Card with NVMe",
    "CreatedBy" : "admin",
    "CreatedOn" : ISODate("2019-09-05T21:17:08.370Z"),
    "UpdatedOn" : ISODate("2019-09-05T21:17:04.806Z"),

    J 1 Reply Last reply
    0
    • J jkirkerx

      So I created this user interface to manage the sub categories of a category. I have the whole document loaded in Angular V7+ as a model, and I just list the sub categories in a table. Now I have a search interface in which I'd like to query to sub categories to find a specific one. In all my other uses of search, I call a service to .Net Core and let core find the answer and return them. Well that's easy because I'm loading documents. But this time I'd like to just search the model in the DOM. In other words find the data within the document. This way I can edit the document and return the whole document upon a change and let Core update it. So I can find the Sub Category, but I'd like to reorder the array. Show the search results first and then the rest in TypeScript. Right now I'm just loading the result in a Modal UI for editing. But I will run into this in the future so I should figure it out. Not sure if I'm approaching this right or not as far as my document design goes. Of if it's not feasible to do and I should write a service for it and let Core do the work. I looked at this [javascript - Reordering arrays - Stack Overflow](https://stackoverflow.com/questions/2440700/reordering-arrays). I can sort the list, and splice, but this is more complicated to me. By the way, result just returns 1 record even if 2 exists. eg.

      {
      "_id" : "5d702eab43c22b1674a8e680",
      "Name" : "SSD Drives",
      "Description" : "Solid State Hard Drives",
      "Image" : {
      "_id" : null,
      "Name" : null,
      "Alt" : null,
      "Data" : null,
      "Base64" : null,
      "Url" : null,
      "Type" : null
      },
      "CreatedBy" : "admin",
      "CreatedOn" : ISODate("2019-09-04T21:37:47.331Z"),
      "UpdatedOn" : ISODate("2019-09-06T16:58:16.464Z"),
      "Selected" : false,
      "SubCategories" : [
      {
      "_id" : "5d717a48675cc0229cf15ee5",
      "Name" : "SATA",
      "Description" : "2 1/2\" Sata 3 Drive",
      "CreatedBy" : "admin",
      "CreatedOn" : ISODate("2019-09-05T21:12:41.633Z"),
      "UpdatedOn" : ISODate("2019-09-05T21:12:18.721Z"),
      "Selected" : false
      },
      {
      "_id" : "5d717b54c4653d1c24753241",
      "Name" : "PCIe",
      "Description" : "PCI Addon Card with NVMe",
      "CreatedBy" : "admin",
      "CreatedOn" : ISODate("2019-09-05T21:17:08.370Z"),
      "UpdatedOn" : ISODate("2019-09-05T21:17:04.806Z"),

      J Offline
      J Offline
      jkirkerx
      wrote on last edited by
      #2

      I'm getting closer now. Getting better with push, unshift and splice now. I changed the way the interface works, where I can now reload the original sub categories after search with a reload button. And instead of sending the category back to the .Net API, I rewrote the API to work with one sub category at a time. Just need to figure out how to get more than 1 result back.

      searchSubCategories() {

      const query = this.subCategoriesForm.controls["searchQuery"].value;
      if (query) {
      const results = this.model.SubCategories
      .find(q => q.Name.toLowerCase().includes(query.toLowerCase(), 0)
      || q.Description.toLowerCase().includes(query.toLowerCase(), 0));
      if (results) {
      const index = this.model.SubCategories.indexOf(results);
      this.model.SubCategories.splice(index, 1);
      this.model.SubCategories.unshift(results);
      }
      }
      }

      If it ain't broke don't fix it Discover my world at jkirkerx.com

      N W 2 Replies Last reply
      0
      • J jkirkerx

        I'm getting closer now. Getting better with push, unshift and splice now. I changed the way the interface works, where I can now reload the original sub categories after search with a reload button. And instead of sending the category back to the .Net API, I rewrote the API to work with one sub category at a time. Just need to figure out how to get more than 1 result back.

        searchSubCategories() {

        const query = this.subCategoriesForm.controls["searchQuery"].value;
        if (query) {
        const results = this.model.SubCategories
        .find(q => q.Name.toLowerCase().includes(query.toLowerCase(), 0)
        || q.Description.toLowerCase().includes(query.toLowerCase(), 0));
        if (results) {
        const index = this.model.SubCategories.indexOf(results);
        this.model.SubCategories.splice(index, 1);
        this.model.SubCategories.unshift(results);
        }
        }
        }

        If it ain't broke don't fix it Discover my world at jkirkerx.com

        N Offline
        N Offline
        Nathan Minier
        wrote on last edited by
        #3

        Okay, the reason that you're getting one result is that everything that you're doing is intended to operate on only one element. Array.find(), for instance, is basically the JS version of .FirstOrDefault(). Array.indexOf() is a single element as well. The best thing to do in this case is to create a new array, populate it with your search results, and sort it based on your criteria. For instance:

        searchSubCategories() {
        if(this.subCategoriesForm.controls["searchQuery"].value){
        let query = this.subCategoriesForm.controls["searchQuery"].value.toLowerCase();

          this.model.searchResults = 
             this.model.SubCategories.map(sub => {
                if(sub.Name.toLowerCase().includes(query)){
                   return {
                      subCategory: sub,
                      foundIn: 'name'
                   }
                }
        
                if(sub.Description.toLowerCase().includes(query)){
                   return {
                      subCategory: sub,
                      foundIn: 'description'
                   };
                }
          });   
        
          this.model.searchResults.sort((a,b) => {
             // sort relevance based on if term is found in name or if in description
             if(a.foundIn !== b.foundIn){
                if(a.foundIn === 'name'){
                   return -1
                }
                if(b.foundIn === 'name')
                {
                   return 1;
                }
             }
             return 0;
          });
        

        }
        }

        This will give you an array attached to your model that has your subcategories, then you can data-bind that array to your result widget.

        "Never attribute to malice that which can be explained by stupidity." - Hanlon's Razor

        J 2 Replies Last reply
        0
        • N Nathan Minier

          Okay, the reason that you're getting one result is that everything that you're doing is intended to operate on only one element. Array.find(), for instance, is basically the JS version of .FirstOrDefault(). Array.indexOf() is a single element as well. The best thing to do in this case is to create a new array, populate it with your search results, and sort it based on your criteria. For instance:

          searchSubCategories() {
          if(this.subCategoriesForm.controls["searchQuery"].value){
          let query = this.subCategoriesForm.controls["searchQuery"].value.toLowerCase();

            this.model.searchResults = 
               this.model.SubCategories.map(sub => {
                  if(sub.Name.toLowerCase().includes(query)){
                     return {
                        subCategory: sub,
                        foundIn: 'name'
                     }
                  }
          
                  if(sub.Description.toLowerCase().includes(query)){
                     return {
                        subCategory: sub,
                        foundIn: 'description'
                     };
                  }
            });   
          
            this.model.searchResults.sort((a,b) => {
               // sort relevance based on if term is found in name or if in description
               if(a.foundIn !== b.foundIn){
                  if(a.foundIn === 'name'){
                     return -1
                  }
                  if(b.foundIn === 'name')
                  {
                     return 1;
                  }
               }
               return 0;
            });
          

          }
          }

          This will give you an array attached to your model that has your subcategories, then you can data-bind that array to your result widget.

          "Never attribute to malice that which can be explained by stupidity." - Hanlon's Razor

          J Offline
          J Offline
          jkirkerx
          wrote on last edited by
          #4

          Wow!

          Nathan Minier wrote:

          Okay, the reason that you're getting one result is that everything that you're doing is intended to operate on only one element. Array.find(), for instance, is basically the JS version of .FirstOrDefault(). Array.indexOf() is a single element as well.

          I didn't know that but it makes sense since it behaves like that. I really need to take a night and read up on modern JavaScript/TypeScript and arrays. I was wondering if it was possible to do. Map then Sort. I would of never guessed that "Map" would return multiple results, and it's use looks complicated but I get it. Nice job on this! You must have a ton of experience with modern JavaScript or was just curious last night and did the research I should of done. I can see where this knowledge can be really handy for me working with Angular/React/Vue. Thanks Nathan.

          If it ain't broke don't fix it Discover my world at jkirkerx.com

          N 1 Reply Last reply
          0
          • J jkirkerx

            Wow!

            Nathan Minier wrote:

            Okay, the reason that you're getting one result is that everything that you're doing is intended to operate on only one element. Array.find(), for instance, is basically the JS version of .FirstOrDefault(). Array.indexOf() is a single element as well.

            I didn't know that but it makes sense since it behaves like that. I really need to take a night and read up on modern JavaScript/TypeScript and arrays. I was wondering if it was possible to do. Map then Sort. I would of never guessed that "Map" would return multiple results, and it's use looks complicated but I get it. Nice job on this! You must have a ton of experience with modern JavaScript or was just curious last night and did the research I should of done. I can see where this knowledge can be really handy for me working with Angular/React/Vue. Thanks Nathan.

            If it ain't broke don't fix it Discover my world at jkirkerx.com

            N Offline
            N Offline
            Nathan Minier
            wrote on last edited by
            #5

            Sure thing! Map is honestly really easy. It just performs an operation on each element in the array (as defined in the anonymous function there) and will return a new array of items returned from that function. If you're familiar with LINQ, think ".Select(x => function(x){ return something;});" And yes, I've been putting myself through a Vue "upload" over the last couple of weeks, after finally biting the bullet and hopping on the webpack train, so this stuff is all fresh :)

            "Never attribute to malice that which can be explained by stupidity." - Hanlon's Razor

            J 1 Reply Last reply
            0
            • N Nathan Minier

              Sure thing! Map is honestly really easy. It just performs an operation on each element in the array (as defined in the anonymous function there) and will return a new array of items returned from that function. If you're familiar with LINQ, think ".Select(x => function(x){ return something;});" And yes, I've been putting myself through a Vue "upload" over the last couple of weeks, after finally biting the bullet and hopping on the webpack train, so this stuff is all fresh :)

              "Never attribute to malice that which can be explained by stupidity." - Hanlon's Razor

              J Offline
              J Offline
              jkirkerx
              wrote on last edited by
              #6

              What is the webpack train? I'm about 13 to 15 months into Angular now, started at V5. And I'm on my 3rd generation of Angular wrapped in .Net Core V2.2+. Which means I was finally able to wrap natural Angular with CLI into .Net Core and switched to @ngtools/webpack for super fast compression of everything. The VS 2017 Angular template was really bad and I had to create my own from scratch. But MS created SPA services that was a huge help in building the app now. I got the Docker part down now, building a Linux container for my website on my Windows rig and deploying the containers to my Ubuntu Linux servers. Dumped my Windows servers with Virtual Machines for Ubuntu/Docker/Kubernetes with SSD enterprise drives. Linux Docker is a trip with .Net Core, the slashes "\" vs "/" for file paths are different so you have to handle both. It's been a long hard journey but well worth it. I'm very happy with this technology and I'm not looking back. But support and help with this is hard to find.

              If it ain't broke don't fix it Discover my world at jkirkerx.com

              1 Reply Last reply
              0
              • N Nathan Minier

                Okay, the reason that you're getting one result is that everything that you're doing is intended to operate on only one element. Array.find(), for instance, is basically the JS version of .FirstOrDefault(). Array.indexOf() is a single element as well. The best thing to do in this case is to create a new array, populate it with your search results, and sort it based on your criteria. For instance:

                searchSubCategories() {
                if(this.subCategoriesForm.controls["searchQuery"].value){
                let query = this.subCategoriesForm.controls["searchQuery"].value.toLowerCase();

                  this.model.searchResults = 
                     this.model.SubCategories.map(sub => {
                        if(sub.Name.toLowerCase().includes(query)){
                           return {
                              subCategory: sub,
                              foundIn: 'name'
                           }
                        }
                
                        if(sub.Description.toLowerCase().includes(query)){
                           return {
                              subCategory: sub,
                              foundIn: 'description'
                           };
                        }
                  });   
                
                  this.model.searchResults.sort((a,b) => {
                     // sort relevance based on if term is found in name or if in description
                     if(a.foundIn !== b.foundIn){
                        if(a.foundIn === 'name'){
                           return -1
                        }
                        if(b.foundIn === 'name')
                        {
                           return 1;
                        }
                     }
                     return 0;
                  });
                

                }
                }

                This will give you an array attached to your model that has your subcategories, then you can data-bind that array to your result widget.

                "Never attribute to malice that which can be explained by stupidity." - Hanlon's Razor

                J Offline
                J Offline
                jkirkerx
                wrote on last edited by
                #7

                I opted for this. The foundIn forced me to create another class for search Results that wasn't compatible with what I have already. But your example works great, and I did rewrite it from scratch.

                export interface SubCategorySearchResults {
                subCategory: SubCategories;
                foundIn: string;
                }
                export class SubCategories {
                Id: string;
                Name: string;
                Description: string;
                CreatedBy: string;
                CreatedOn: Date;
                UpdatedOn: Date;
                Selected: boolean;
                }

                // And produced this JSON

                [{"subCategory":{"Id":"5d7fd71ef9a41e064ce3cbd9","Name":"Super Thick","Description":"Non moving gel","CreatedBy":"admin","CreatedOn":"2019-09-16T18:40:30.887Z","UpdatedOn":"2019-09-16T18:40:30.859Z","Selected":false},"foundIn":"Name"},{"subCategory":{"Id":"5d7fd63bf9a41e064ce3cbd8","Name":"Thick","Description":"Very Slow Moving Gels","CreatedBy":"admin","CreatedOn":"2019-09-16T18:36:43.762Z","UpdatedOn":"2019-09-16T18:36:43.718Z","Selected":false},"foundIn":"Name"},{"subCategory":{"Id":"5d7fd418f9a41e064ce3cbd6","Name":"Thin ","Description":"Fast moving","CreatedBy":"admin","CreatedOn":"2019-09-16T18:27:36.675Z","UpdatedOn":"2019-09-16T18:27:36.645Z","Selected":false},"foundIn":"Name"}]

                What I wrote, I went back to the const because it self creates a model and just rewrote my this.model.SubCategories. It's a work in progress. Thanks!

                searchSubCategories2(): void {

                const query = this.subCategoriesForm.controls["searchQuery"].value.toLowerCase();
                if (query) {
                const results = this.model.SubCategories.map(sub => {
                if (sub.Name.toLowerCase().includes(query)) {
                return { subCategory: sub, foundIn: "Name" };
                }
                if (sub.Description.toLowerCase().includes(query)) {
                return { subCategory: sub, foundIn: "Description" };
                }
                });

                if (results) {
                  results.sort((a, b) => {
                    if (a.foundIn !== b.foundIn) {
                      if (a.foundIn === "Name") { return -1; }
                      if (b.foundIn === "Name") { return 1; }
                    }
                    return 0;
                  });
                
                  this.model.SubCategories = \[\];
                  results.forEach(result => {
                    this.model.SubCategories.push(result.subCategory);
                  });
                
                  console.log(JSON.stringify(results));
                  console.log(JSON.stringify(this.model.SubCategories));
                }
                

                }
                }

                If it ain't broke don't fix it Discover my world at jkirkerx.com

                1 Reply Last reply
                0
                • J jkirkerx

                  I'm getting closer now. Getting better with push, unshift and splice now. I changed the way the interface works, where I can now reload the original sub categories after search with a reload button. And instead of sending the category back to the .Net API, I rewrote the API to work with one sub category at a time. Just need to figure out how to get more than 1 result back.

                  searchSubCategories() {

                  const query = this.subCategoriesForm.controls["searchQuery"].value;
                  if (query) {
                  const results = this.model.SubCategories
                  .find(q => q.Name.toLowerCase().includes(query.toLowerCase(), 0)
                  || q.Description.toLowerCase().includes(query.toLowerCase(), 0));
                  if (results) {
                  const index = this.model.SubCategories.indexOf(results);
                  this.model.SubCategories.splice(index, 1);
                  this.model.SubCategories.unshift(results);
                  }
                  }
                  }

                  If it ain't broke don't fix it Discover my world at jkirkerx.com

                  W Offline
                  W Offline
                  Wishe1991
                  wrote on last edited by
                  #8

                  I changed the way how interface work and reloaded. It’s working.

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups