0

I have two array objects which is of different lengths in which data.rows is of length 955 and place_names is of length 287. I am running loop inside the loop which takes around 3 minutes to run. Is there any easy and fastest way to run the code below?

for (i = 0; i < place_names.length; i++) {
  for (j = 0; j < data.rows.length; j++) {
    if (place_names[i].name === data.rows[j].name) {
      geom.push(data.rows[j].st_asgeojson);
      geom1.push({
        name: data.rows[j].name,
        geometry: data.rows[j].st_asgeojson
      });
      matched_average_value.push(place_names[i].average);
      matched_sum_value.push(place_names[i].sum);
      matched_minimum_value.push(place_names[i].minmum);
      matched_maximum_value.push(place_names[i].maximum);
    }
    else {
      console.log("no matches found");
    }
  }
}
Kaspar Lee
  • 5,446
  • 4
  • 31
  • 54
Harnish
  • 101
  • 1
  • 10
  • You can try this and compare. But I don't think it is gonna make much difference. Fiddle: https://jsfiddle.net/xoowvcf9/ – Rayon Dec 17 '15 at 12:43
  • 1
    are `i` and `j` local variables ? you could sort both list by name. – Hacketo Dec 17 '15 at 12:43
  • @Hacketo, Sorting will go through another loop right ? But that won't be nested one. Kind of helpful! Also you somewhere need to break a loop I suppose. `if (place_names[i].name === data.rows[j].name)` here ? – Rayon Dec 17 '15 at 12:46
  • @RayonDabre sorting would allow to stop inner loop when reach the last item that match, and you could start the inner loop at the last item that previously match. – Hacketo Dec 17 '15 at 12:46
  • defining the length of the array before the loop also helps in performace – Keyboard ninja Dec 17 '15 at 12:47
  • 1
    remove the `console.log` ... where you have it will result in up to 274000+ pointless console.logs – Jaromanda X Dec 17 '15 at 12:47
  • @JaromandaX, Let us assume it is just there in development environment... – Rayon Dec 17 '15 at 12:48
  • You forgot a few `{}`. And as @JaromandaX said, remove the `console.log()` statements! – Kaspar Lee Dec 17 '15 at 12:48
  • @Hacketo: i is global and j is local. – Harnish Dec 17 '15 at 12:50
  • Well even console.log is removed, it is bit slower. – Harnish Dec 17 '15 at 12:51
  • Can we see some data samples? Are names unique? – Oka Dec 17 '15 at 12:51
  • Borrowing @RayonDabre code and added a few more tweaks which may or may not help - [fiddle](https://jsfiddle.net/w5af89yc/2/) – Jaromanda X Dec 17 '15 at 12:52
  • Never heard of js loops taking _minutes_ to execute.. __Something must be going wrong__ Share some example.. – Rayon Dec 17 '15 at 12:52
  • I suspect your bottleneck is not in the nested loops itselfs but in the work that you do inside them. Maybe you should try a different approach, if your if (place_names[i].name === data.rows[j].name) condition is true in a high percentage of cases. – Bardo Dec 17 '15 at 12:54
  • @JaromandaX, `break` and _sorting_ together will help I guess...Correct me I am going wrong... – Rayon Dec 17 '15 at 12:55
  • @Harnish: Start by making `i` a local variable as well. Scope is important for speed. Even a 300k loop should not take minutes. Same for all the other variables you're using… – Bergi Dec 17 '15 at 13:08
  • Are the names unique per array, do you have a 1-to-1 relationship between the items? Have a look at [my answer to *Compare two multidimensional arrays in javascript*](http://stackoverflow.com/a/13484419/1048572) – Bergi Dec 17 '15 at 13:11
  • AJaromanda X: the fiddle given by you https://jsfiddle.net/w5af89yc/2/ works little faster than mine. – Harnish Dec 17 '15 at 13:30

1 Answers1

0

You have two lists place_names and data.rows. The field you're interested in is the name field.

Depending on where you get this data from, it might be better to use a dictionary for this:

var dict = {};
place_names.forEach(
    function(place_name) {
        dict[place_name.name]=place_name;
    }
);

Now you can loop through your data.rows:

data.rows.forEach(
    function(row) {
        if(row.name in dict) {
            var place_name = dict[row.name];
            // Do what needs to be done with "row" and "place_name"
        }
    }
);

This should reduce your n^2 algorithm to a n log n or even n (Depending on JavaScript's dictionary indexing complexity, I'm not sure). This solution assumes that all place_names[i].name values are unique. If they aren't, then you might want to store a list of all matching place_names in your dict.

Sriram
  • 146
  • 7