Snippets – Filtering JSON Using jQuery Grep, Filter, Map

6327_image_58FAEDFAWhen you have a JSON array, you may want to get one or more items from the array and display. jQuery offers two functions that can help: grep and filter.

  • $.grep(). Finds the elements of an array which satisfy a filter function. The original array is not affected.
  • $filter(). Reduce the set of matched elements to those that match the selector or pass the function’s test.
  • $.map(). applies a function to each item in the array, thus returning a modified array

In other words, $.grep() removes items from an array as necessary so that all remaining items pass a provided test; .filter() constructs a new jQuery object from a subset of the matching elements.

Also, filter is intended to be used with html elements, and that is why it is a chainable function that returns a jQuery object and it accepts filters like “:even”, “:odd” or “:visible” etc. You can’t do that with the grep function, which is intended to be a utility function for arrays.

Suppose you have data like this:

https://gist.github.com/devdays/4ba2546cbdc90042b9ea

Grep

$.grep() method removes items from an array as necessary so that all remaining items pass a provided test.

The test is a function that is passed an array item and the index of the item within the array. Only if the test returns true will the item be in the result array.


// Get just the toys by grep on products
var toys = $.grep(myData.products, function (element, index) {
// return whether myData.products.category == 'Toy'
return element.category == "Toy";
});
// toys is a new array of the matching products
$.each(toys, function (i) {
$('#toys').append("<li class='toy'>" + toys[i].name + "</li>");
});

And you can perform multiple tests.


// demonstrate how Grep can have multiple criteria
var expensiveToys = $.grep(myData.products, function (element, index) {
return element.category == "Toy" && element.price > 9;
});

Filter

jQuery’s .filter() method constructs a new jQuery object from a subset of the matching elements.

The parameter for filter can take any one of the following:

  • A selector
  • A function where you will provide a test, similar to that of grep
  • An element
  • A jQuery object.

For a common example, you can use the filter to color the even items in a list:


// Filter the results of the list items
$(".toy").filter(':even').css('background-color', 'khaki');

When using a test function with an JavaScript array, your test looks similar to the grep:


var games = $(myData.products).filter(function (index) {
return myData.products[index].category == "Game";
});

And you receive back the entire array. And when you view the returned value game by calling console.log(JSON.stringify(games)) you see:


{
"0":{"name":"Board Game 1","category":"Game","price":35},
"1":{"name":"Card Game 1","category":"Game","price":8.5},
"2":{"name":"Poker","category":"Game","price":75.5},"length":3,
"prevObject": {
"0":{"name":"Slinky","category":"Toy","price":9.56},
"1":{"name":"Hamburger","category":"Grocery","price":2.49},
"2":{"name":"Squirt Gun","category":"Toy","price":8.5},
"3":{"name":"Board Game 1","category":"Game","price":35},
"4":{"name":"Card Game 1","category":"Game","price":8.5},
"5":{"name":"Poker","category":"Game","price":75.5},
"6":{"name":"Blocks","category":"Toy","price":2.5},
"7":{"name":"Tricycle","category":"Toy","price":95},
"8":{"name":"Jacks","category":"Toy","price":3.5},
"9":{"name":"Lettuce","category":"Grocery","price":25},"length":10
}
}

Map

When you want to apply a change to the array and return a modified array, use $.map(). The syntax used inside the function block is identical to the syntax used with $.grep(). The only difference is that you receive a modified array, not a filtered one.

The translation function you provide is called for each top-level element in the array or object and is passed two arguments: The element’s value and its index or key within the array or object.

The function can return:

  • the translated value, which will be mapped to the resulting array
  • null or undefined, to remove the item
  • an array of values, which will be flattened into the full array

This means you can do both filtering and do some additional changes to the array. For example, you could get a list of the products in the Grocery category. When the product matches a Grocery category, then you can add a new field named myProductIndex  whose value is the offset to the item from my product array. And if it does not match, return null.


var groceryIndices = $.map(myData.products, function (val, i) {
return val.category == "Grocery" ? val.myProductIndex = i : null;
});

In fact, the myData.product array has changed for the Grocery items with those products having a new field. And groceryIndices includes the indices to the offset in my product array:


{
"0":{"name":"Board Game 1","category":"Game","price":35},
"1":{"name":"Card Game 1","category":"Game","price":8.5},
"2":{"name":"Poker","category":"Game","price":75.5},
"length": 3,
"prevObject":{
"0":{"name":"Slinkey","category":"Toy","price":9.56},
"1":{"name":"Hamburger","category":"Grocery","price":2.49},
"2":{"name":"Squirt Gun","category":"Toy","price":8.5},
"3":{"name":"Board Game 1","category":"Game","price":35},
"4":{"name":"Card Game 1","category":"Game","price":8.5},
"5":{"name":"Poker","category":"Game","price":75.5},
"6":{"name":"Blocks","category":"Toy","price":2.5},
"7":{"name":"Tricycle","category":"Toy","price":95},
"8":{"name":"Jacks","category":"Toy","price":3.5},
"9":{"name":"Lettuce","category":"Grocery","price":25},
"length":10}
}

Then later, I can go back to my product array and find each grocery item with the new field. Use the value ( the index parameter is the index in the groceryIndices array).


$.each(groceryIndices,function(index, value) {
console.log(JSON.stringify(myData.products[value]));
});

view raw

jQuery-Map.js

hosted with ❤ by GitHub

Where the console writes:


{"name":"Hamburger","category":"Grocery","price":2.49,"myProductIndex":1}
{"name":"Lettuce","category":"Grocery","price":25,"myProductIndex":9}

Summary

You have seen how you can use grep, filter, and map to get the items you want from within JSON data.

  • grep provides a clean way of getting the data from the items you want.
  • filter provides ways to change the display and give you access to the entire array after your filtering
  • map provides you with a way to get the data, change it, and then reuse the data as needed.

Sample Code

Sample code for this post on jQuery is available in DevDays GitHub repository. See https://github.com/devdays/single-page-app/tree/master/jQuery 

References