Amanda Kitson
Amanda Kitson

Reputation: 5547

jquery .filter() function on large array is slow in IE

I have an array of javascript objects containing about 6300 elements.

I am trying to use jQuery to iterate through those elements and create lists of options for several drop-down lists that can be used to filter those 6300 elements.

In Firefox, this works with no problem, but in IE, I get an error about the script running slow. I've been playing with the code trying to get a set of the data without causing that IE error, but so far, I've had no luck. Below are the methods I have already tried:

Using "indexOf" to create a distinct list of "Jurisdictions".

    var arrayJurisdiction = dataSet.filter(function (item, i, a) {
        return i.Jurisdiction == a.indexOf(item.Jurisdiction);
    });

Iterating over each element, checking to see if the value already exists in the secondary array, and if it doesn't, then adding it.

    g$.each(dataSet, function (key, value) {
        var matchingJurisdiction = arrayJurisdiction.filter(function (item) {
            return value.Jurisdiction == item;
        })[0];
        if (matchingJurisdiction == null) {
            arrayJurisdiction.push(value.Jurisdiction);
        }
    });

Both of these methods result in IE giving me an error about a script running too slowly. Is there any faster way of doing this?

*EDIT*** Based on feedback below, I have changed the method to use for loops instead of .each() and .filter(), but I am still receiving the "stop this script?" dialog in IE.

Here is the revised code, using the for loops. Also, I have included all the filters I am attempting to fill (not just the first one).

    for (var i = 0; i < dataSet.length; i++) {
        var value = dataSet[i];

        var matchingJurisdiction = null;
        for (var i = 0; i < arrayJurisdiction.length; i++) {
            var item = arrayJurisdiction[i];
            if (item == value.Jurisdiction) {
                matchingJurisdiction == item;
                break;
            }
        }
        if (matchingJurisdiction == null) {
            arrayJurisdiction.push(value.Jurisdiction);
        }



        var valueYear = new Date(value.Treatment_Date).getFullYear();
        var matchingYear = null;
        for (var i = 0; i < arrayYear.length; i++) {
            var item = arrayYear[i];
            if (item == valueYear) {
                matchingYear == item;
                break;
            }
        }

        if (matchingYear == null) {
            arrayYear.push(valueYear);
        }
        var matchingProjectClass = null;
        for (var i = 0; i < arrayProjectClass.length; i++) {
            var item = arrayProjectClass[i];
            if (item == valueYear) {
                matchingProjectClass == item;
                break;
            }
        }
        if (matchingProjectClass == null) {
            arrayProjectClass.push(value.Project_Classification);
        }

        var matchingImprovementType = null;
        for (var i = 0; i < arrayImprovementType.length; i++) {
            var item = arrayImprovementType[i];
            if (item == valueYear) {
                matchingImprovementType == item;
                break;
            }
        }
        if (matchingImprovementType == null) {
            arrayImprovementType.push(value.Improvement_Type);
        }
    }

Upvotes: 0

Views: 2307

Answers (1)

Ilia G
Ilia G

Reputation: 10221

Dropping jQuery each() is certainly an option as it does some funny stuff with the scope beside actual iteration. Another real is that your algorithm seem to be O(n^2) which is pretty bad. I would simply sort your dataSet on Jurisdiction value, and then loop over keeping previous value and eliminating duplicates. That is going to be the O of the sort algorithm, which is likely using quick sort algorithm O(n*log(n)), but is also likely implemented much more efficiently in native code.

dataSet.sort(function(a, b)
{
    if (a.Jurisdiction > b.Jurisdiction)
        return 1;
    if (a.Jurisdiction < b.Jurisdiction)
        return -1;
    return 0;
});

var prev = null;
var filtered = new Array(dataSet.length);
for (var i=0; i<dataSet.length; i++)
{
    if (prev == null || prev.Jurisdiction != dataSet[i].Jusrisdiction)
        filtered.push(dataSet[i]);
    prev = dataSet[i];
}

Upvotes: 1

Related Questions