james
james

Reputation: 4049

How to use jQuery Grep to filter extremely nested JSON

I'm too new at JS to know how to write a return properly. Basically lenders is an array of people, each of whom have items, each of which has requests, each of which has a start and end date. When the user punches in a start/end date to search, I need to look through the JSON object, and IF any item has a request that has a start/end date that overlaps with what the user has searched for, then that item needs to be excluded from the results.

Original lenders JSON

[
  {"email":"[email protected]","inventories":
    [
      {"name":"2-Person Tent","requests":
        [
          {"pickupdate":"2015-01-03","returndate":"2015-01-08"},
          {"pickupdate":"2015-02-01","returndate":"2015-02-02"}
        ]
      },
      {"name":"Sleeping bag","requests":
        [
          {"pickupdate":"2015-02-01","returndate":"2015-02-02"}
        ]
      },
      {"name":"Sleeping bag","requests":[]},
    ]
  },
  {"email":"[email protected]",,"inventories":[]}
] 
...

If the user searches for pickupdate 2015-01-03 until returndate 2015-01-07 for example, that overlaps with a request for a 2-person tent, and so the result of the grep function should be:

New lenders JSON

[
  {"email":"[email protected]","inventories":
    [
      // 2-Person tent has been removed by grep function
      {"name":"Sleeping bag","requests":
        [
          {"pickupdate":"2015-02-01","returndate":"2015-02-02"}
        ]
      },
      {"name":"Sleeping bag","requests":[]},
    ]
  },
  {"email":"[email protected]",,"inventories":[]}
] 
...

I have a great starting point from @Олег Ильин that helped me figure out how to drill down into the Request objects, but the is_valid part is not working, the returned array of inventories the exact same before and after the grep function. Additional help?

  function FilterLenders() { 
    console.log(lenders[0].inventories)
    for(var n=0; n<lenders.length; n++){
      inventories = lenders[n].inventories
      inventories = jQuery.grep(inventories, function (inventory) {
        var is_valid;
        requests = inventory.requests;
        for(var x=0; x<requests.length; x++){
          var pickupdate_request = moment(requests[x].pickupdate)
          var returndate_request = moment(requests[x].returndate)
          var test = (pickupdate_request - returndate_search) * (pickupdate_search - returndate_request)
          if(test > 0) {
            //dates completely overlap the item that had this request needs to be excluded
            is_valid = false;
          } else if(test === 0) {
            //dates are on the edge of each other, for now the item that had this request can be included
            is_valid = true;
          } else if(test <0) {
            //dates do not overlap at all, item should definitely be included
            is_valid = true
          }
        }
      })
    }
    console.log(lenders[0].inventories) //first object, 2-person tent, should not exist
  }

Also, had another idea to do this, but the problem is that here, it never returns false, even though if I put a console.log("false"), that would show me a false exists

function FilterLenders() { 
  console.log(lenders[1].inventories)
  for(var n=0; n<lenders.length; n++){
    inventories = lenders[n].inventories
    inventories = jQuery.grep(inventories, function (inventory) {
      function check(inventory) {
        requests = inventory.requests;
        for(var x=0; x<requests.length; x++){
          var pickupdate_request = moment(requests[x].pickupdate)
          var returndate_request = moment(requests[x].returndate)
          var test = (pickupdate_request - returndate_search) * (pickupdate_search - returndate_request)
          if(test > 0) {
            //dates completely overlap the item that had this request needs to be excluded
            return false;
            //altho return doesn't seem to work, if I put a console.log("false") here it will correctly log a false entry...
            break;
          } else if(test === 0) {
            //dates are on the edge of each other, for now the item that had this request can be included
            return true;
          } else if(test <0) {
            //dates do not overlap at all, item should definitely be included
            return true;
          }
        }
      }
      console.log(check(inventory))
      if( check(inventory) ) {
        return inventory
      }
    })
  }
  console.log(lenders[1].inventories) //object 5 should not exist
}

Upvotes: 0

Views: 1360

Answers (2)

gliviu
gliviu

Reputation: 81

If jquery.grep solution is too complex you can use specialized filters as json easy filter See this plunkr

var start = new Date('2015-01-03');
var end = new Date('2015-01-07');
var success = new Jef(data).remove(function (node) {
    if (node.has('requests')) {
        var requests = node.value.requests;
        for (var i = 0; i < requests.length; i++) {
            var request = requests[i];
            var pick = new Date(request.pickupdate);
            var ret = new Date(request.returndate);
            if (!((pick < start && ret < start) || (pick > end && ret > end))) {
                // pickupdate-returndate overlaps with start-end
                return node;
            }
        }
    }
});

alert(JSON.stringify(data, null, 4));

Upvotes: 1

Олег Ильин
Олег Ильин

Reputation: 21

Function:

function moment(date){
    var y = date.substring(0,4),
        m = date.substring(5,7),
        d = date.substring(8,10),
        newdate = new Date(y, m, d);

    return newdate.getTime();
}

pickupdate_search = '2015-01-03';
returndate_search = '2015-01-07';

function FilterLenders() {
console.log(lenders[0]);

for (var n = 0; n < lenders.length; n++) {
    inventories = lenders[n].inventories;
    lenders[n].inventories = jQuery.grep(inventories, function(inventory) {
            var is_valid,
                x = 0,
                requests = inventory.requests,
                l = requests.length;

            for (; x < l; x++) {
                var pickupdate_request = moment(requests[x].pickupdate),
                    returndate_request = moment(requests[x].returndate),
                    return_search = moment(returndate_search),
                    pickup_search = moment(pickupdate_search);

                    if((pickup_search >= pickupdate_request) && (return_search <= returndate_request)){
                        //dates completely overlap the item that had this request needs to be excluded
                        is_valid = false;
                        console.log('false');
                        break;
                    }else{
                        console.log('true');
                        is_valid  = true;
                    }
            }
            return is_valid;
        }); 
    }
    console.log(lenders[0]); //first object, 2-person tent, should not exist
}
FilterLenders();

Upvotes: 0

Related Questions