简体   繁体   中英

How to search JSON array with search filter form?

I have a JSON array and a search form with multiple filters. In this search form I have 4 select drop down fields for filtering. How can I search the JSON array based on what the user selects and then display the results after they hit the submit button?

For instance If the user selects "Burger" in the "Food Select Drop Down" field and "Coke" in the "Drink Select Drop Down" field. I want to be able to display all the restaurants that offer both of those items. Is this possible?

var restaurants = [
            {"restaurant" : { "name" : "McDonald's", "food" : "burger", "drink" : "coke", "content" : "Lorem ipsum dolor sit amet" }},
            {"restaurant" : { "name" : "KFC", "food" : "chicken", "drink" : "pepsi", "content" : "Lorem ipsum dolor sit amet" }},
            {"restaurant" : { "name" : "Pizza Hut",  "food" : "pizza", "drink" : "sprite", "content" : "Lorem ipsum dolor sit amet" }},
            {"restaurant" : { "name" : "Dominos",  "food" : "pizza", "drink" : "root beer", "content" : "Lorem ipsum dolor sit amet" }},
            {"restaurant" : { "name" : "Popeyes",  "food" : "chicken", "drink" : "mist", "content" : "Lorem ipsum dolor sit amet" }}
          ];

One way to filter the array is the following

function filter( restaurants, food, drink) { 

    var result = [];

    for( var i= 0, len = restaurants.length; i < len; i++) {
        var el = restaurants.restaurant[i];

        if( el.food === food && el.drink === drink ) {
            result.push( el );
        }
    }

    return result;
}

A more functional way

You can use the filter method defined in the Array prototype

function customFilter(food, drink) {
   return function(el) {
      var r = el.restaurant;
      return r.food === food && r.drink === drink;
   }
}

restaurants.filter( customFilter('Burger', 'Coke') );

Sophisticated, general use filter

function customFilter(values) {
   return function(el) {
      var r = el.restaurant;
      var keys = Object.keys( values );
      var answer = true;

      for( var i = 0, len = keys.length; i < len; i++) {
          if( r[keys[i]] !== values[keys[i]] ) {
              answer = false;
              break;
          }
      }

      return answer;
   }
}

restaurants.filter( customFilter({'food':'Burger', 'drink': 'Coke'}) );    

JavaScript has a native Array.prototype.filter which accepts a function . You simply want to generate this function when a user chooses the inputs, for example

function filter(a, food, drink) {
    food = food ? food.toLowerCase() : 0;
    drink = drink ? drink.toLowerCase() : 0;
    return a.filter(function (e) {
        if (food && e.restaurant.food.toLowerCase().indexOf(food) === -1)
            return false;
        if (drink && e.restaurant.drink.toLowerCase().indexOf(drink) === -1)
            return false;
        return true;
    });
}

filter(restaurants, 'burger', 'coke');
// [{"restaurant":{"name":"McDonald's","food":"burger","drink":"coke","content":"Lorem ipsum dolor sit amet"}}]

I've gave my vote to Igor's answer, but, because I wanted to put a full example in jsfiddle, here you go: http://jsfiddle.net/jeffrenaud/JDYMt/

I've added the possibility to have an 'Any' options, so that there's no filter on a particular element.

Here's a summary:

HTML:

<label for="food">Food:</label>
<select id="food">
    <option value="">Any</option>
    <option value="burger">Burger</option>
    <option value="chicken">Chicken</option>
    <option value="pizza">Pizza</option>
</select>

<label for="drink">Drink:</label>
<select id="drink">
    <option value="">Any</option>
    <option value="coke">Coke</option>
    <option value="pepsi">Pepsi</option>
    <option value="sprite">Sprite</option>
    <option value="root beer">Root beer</option>
    <option value="mist">Mist</option>
</select>

<ul id="result"></ul>

JavaScript:

var restaurants = [
    {
        "restaurant": {
            "name": "McDonald's",
            "food": "burger",
            "drink": "coke",
            "content": "Lorem ipsum dolor sit amet"
        }
    },
    {
        "restaurant": {
            "name": "KFC",
            "food": "chicken",
            "drink": "pepsi",
            "content": "Lorem ipsum dolor sit amet"
        }
    },
    {
        "restaurant": {
            "name": "Pizza Hut",
            "food": "pizza",
            "drink": "sprite",
            "content": "Lorem ipsum dolor sit amet"
        }
    },
    {
        "restaurant": {
            "name": "Dominos",
            "food": "pizza",
            "drink": "root beer",
            "content": "Lorem ipsum dolor sit amet"
        }
    },
    {
        "restaurant": {
            "name": "Popeyes",
            "food": "chicken",
            "drink": "mist",
            "content": "Lorem ipsum dolor sit amet"
        }
    }
  ];

var $food = $('#food'),
    $drink = $('#drink'),
    $result = $('#result');

$food.change(function () {
    onChange();
});

$drink.change(function () {
    onChange();
});

function onChange() {
    var findedRestaurants = findRestaurants();
    showRestaurants(findedRestaurants);
}

function findRestaurants() {
    return filter($food.find('option:selected').val(), $drink.find('option:selected').val());
}

function filter(food, drink) {
    var result = [];

    for (var i = 0; i < restaurants.length; i++) {
        var restaurant = restaurants[i].restaurant;
        if ((!food || restaurant.food === food) && (!drink || restaurant.drink === drink)) {
            result.push(restaurant);
        }
    }

    return result;
}

function showRestaurants(restaurants) {
    $result.empty();
    for (var i = 0; i < restaurants.length; i++) {
        $result.append($('<li>' + restaurants[i].name + '</li>'));
    }
}

onChange();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM