Reputation: 755
I'm currently in the process of porting one of my working, SQL filter based applications so that rather than querying the database every time a filter is changed, it instead filters from one, single, JavaScript array of objects ("the master array").
// console.log(array)
[Object, Object, Object, ...]
0: Object
date_created: "2014-12-20"
product_id: "1"
product_name: "name"
type: "0"
purchased: "1"
1: Object
date_created: "2014-12-21"
product_id: "2"
product_name: "name2"
type: "1"
purchased: "0"
2: Object
date_created: "2014-12-21"
product_id: "3"
product_name: "name3"
type: "1"
purchased: "0"
... etc etc
At the moment I have the JavaScript array, and I have a basic filtering system happening whereby I can filter out the results to show only basic items (type == 0
), only advanced items (type == 1
), or all items. It will then order by the product name, cost, or date added depending on the order by selected.
The way this works is that it loops through the master array, assigns the current object to a variable, and then loops through that specific object. If show only basic is set (true
), and key == 'type' && value == 0
, then we push that object into a new array. At the end of the master array loop, if the newly array created array is still empty then that means no matches were made. It simply copies the master array across, and then applies some filtering to that array.
My headache, and the bit I cannot wrap my head around, is how do I do multiple filters? An object may be basic
AND purchased
, but my current algorithm would slot that record in twice. That's when I thought about counting the number of inserts, and then doing an array.splice
removing the additional objects, but that failed miserably and returned unwanted results. This was my attempt at that:
function run_filter (type) {
/*ajax_active = true;
$('#loading').show().center();*/
// new empty array
var new_items = [];
// items_length refers to the size of the master array (8 objects in total)
for(var i = 0; i < items_length; i++) {
// grab the current object
var object = all_items[i];
// grab the current size of the new array
var new_items_length = new_items.length;
// reset to 0
var insert_amount = 0;
// for each key in current object
for(var key in object) {
// if show only basic and hide advanced
if (show_basic && !show_advanced) {
if (key == 'type' && object[key] == 0) {
// push the object onto the new array
new_items.push(object);
// incrememnt counter by 1
insert_amount++;
}
}
if (show_advanced && !show_basic) {
if (key == 'type' && object[key] == 1) {
new_items.push(object);
insert_amount++;
}
}
// if we want to hide purchased (i.e. omit records where purchased == 1
if (hide_purchased) {
if (key == 'purchased' && object[key] == 0) {
new_items.push(object);
insert_amount++;
}
}
// if increment counter == 2 or greater (i.e. an object has been inserted twice because it is both basic and hasn't been purchased)
if(insert_amount > 1) {
// new array length BEFORE objects pushed onto new array (+1 to it so that we don't remove the first instance of the object) ; ... < new array length AFTER objects pushed ; increment on loop
for(var index = new_items_length + 1; index < new_items_length + insert_amount; index++) {
// remove the object from the new array at the current index
new_items.splice(index, 1);
}
}
}
}
}
On top of that, what if an item is basic, gets pushed into the new array, but the user has also purchased this record and set the filter to hide purchased. It would show that record because it is basic, and ignore the hide purchased filter. I know I could have hundreds of nested if conditions
, but that seems inefficient...
Any help??!
Upvotes: 0
Views: 584
Reputation: 6770
I think you code can be simplified by using Array.filter() which creates a new array with all elements that pass the test implemented by the provided function.:
function run_filter (type) {
var new_items = all_items.filter(function(obj, index, array) {
// You can do any filter you want here
// Just focus on the filter
return (obj.type == type) && (obj.purchased == "1");
});
return new_items;
}
See this Example
Upvotes: 1