JS search for both object keys and values

I have a large JS Object (around 7000 entries) which looks like,

   var jsobject = {
    "/football/": {
      "title": "(:title)",
      "description": "Shop (:title) online ",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/football/"
    },
    "/league/": {
      "title": "(:title)",
      "description": "Shop (:title) online",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/bayern-munich/p/replica"
    },
    "/club/fulham/": {
      "title": "(:title)",
      "description": "Shop (:title) online for football league",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/fulham/"
    },
    "/championship/": {
      "title": "(:title)",
      "description": "Shop (:title) online for championship",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/socks/"
    }
  };

Now that I wanted to search the object for a search key (say "football") exits either in object "key" or "value".

I have used the following piece of code to achieve this, but it takes more time than expected. This javascript code was written in Angular JS and Javascript. Can you suggest me a quicker method?

                    angular.forEach(
                        Object.keys(jsobject), function (data) {
                            let obj = String(angular.lowercase(JSON.stringify(jsobject[data])));
                            if (obj.includes(searchKey) || String(angular.lowercase(data)).includes(searchKey)) {
                                searchResults[data] = jsobject[data];
                            }
                        },
                        searchResults.jsondata
                    );

I want the output looklike below if I search with "football",

{
    "/football/": {
      "title": "(:title)",
      "description": "Shop (:title) online ",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/football/"
    },
    "/club/fulham/": {
      "title": "(:title)",
      "description": "Shop (:title) online for football league",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/fulham/"
    }
  };

Upvotes: 0

Views: 258

Answers (1)

Keith
Keith

Reputation: 24181

You could use a mix of Object.entries, Array.filter & Array.some to achieve what your after.

Below is an example.

var jsobject = {
    "/football/": {
      "title": "(:title)",
      "description": "Shop (:title) online ",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/football/"
    },
    "/league/": {
      "title": "(:title)",
      "description": "Shop (:title) online",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/bayern-munich/p/replica"
    },
    "/club/fulham/": {
      "title": "(:title)",
      "description": "Shop (:title) online for football league",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/fulham/"
    },
    "/championship/": {
      "title": "(:title)",
      "description": "Shop (:title) online for championship",
      "index": "true",
      "follow": "true",
      "CANONICAL": "/socks/"
    }
  };
  
  
      
  function filterAll(obj, search) {
    return Object.fromEntries(
      Object.entries(obj).filter(([k,v]) => 
        k.toLowerCase().includes(search)
        || Object.entries(v).some(([k,v]) => 
          typeof v === 'string' 
          && v.toLowerCase().includes(search)
    )));
  }
  
  
  console.log(filterAll(jsobject, 'football'));

Upvotes: 1

Related Questions