2 Replies Latest reply on Sep 21, 2009 2:50 AM by axedre

    indexOf() function to search for object.<property> in object array

    axedre

      Hi everyone!
      Ok, I know the topic of this thread sounds a bit awkward, but with an example it will be a lot clearer.
      I have a series of arrays that contain strings, henceforth named "tags"; these tags can occurr only once in every array (which is thus a 'set' of tags, by the mathematical definition of 'set') but more than one array may contain a given tag (the sets' intersections are not always null).
      I want to write a function that cycles through all the tags in all the arrays and counts them, yielding the result in a separate array called tag_counter that contains Tag objects . A Tag object has two fields: 'value', which is the tag itself, and 'occurrences', which keeps count of the times the tag was found.
      The logic of the function is simple: for each array, cycle all its tags; if the tag already exists in the tag_counter array, increment its counter by 1; otherwise, add a new entry in the tag_counter array with the given tag. The line in bold-italics is exactly the point of my question, cause I don't know how to search inside an array of objects by a property of one such object. Here is the code:

       

      private function harvest_tags(dt:DataTable):Array {
          var tag_counter:Array = new Array();
          
          for each(var site_feeds:Object in dt.data) {    //cycle through the Arrays
              for each(var tag:String in site_feeds.t) {  //cycle through the tags
                  if(tag == '') continue;     //in case an empty tag is found, skip it
                  tag = tag.replace(',', ''); //strip commas
                  var i:int = tag_counter.indexOf(tag); //this needs fixing!
                  if(i != -1) {
                      tag_counter[i].occurrences++;
                   }
                  else {
                       tag_counter.push(new Tag(tag));
                   }
               }
           }
      
           tag_counter.sortOn("occurrences", Array.NUMERIC | Array.DESCENDING);
           return tag_counter;
      }
      

       

      and the Tag class definition:

       

      public class Tag {
              private var value:String;
              public var occurrences:Number;
              
              public function Tag(value:String) {
                  this.value = value;
                  this.occurrences = 1;
              }
      }
      

       

      Any help would be greatly appreciated.

       

      Andrea

        • 1. Re: indexOf() function to search for object.<property> in object array
          Flex harUI Adobe Employee

          I think you want to use a hashmap.  The Object class is often used for that.  It is much faster than searching an array of strings.

           

          private function harvest_tags(dt:DataTable):Array {

              var tag_counter:Object = new Object();

               

              for each(var site_feeds:Object in dt.data) {    //cycle through the Arrays

                  for each(var tag:String in site_feeds.t) {  //cycle through the tags

                      if(tag == '') continue;     //in case an empty tag is found, skip it

                      tag = tag.replace(',', ''); //strip commas

                      if (tag_counter[tag])

                         tag_counter[tag]++;

                      else

                            tag_counter[tag] = 1;

                   }

               }

           

               var tag_array:Array = new Array();

           

               for (var p:String in tag_counter) {

                   var tagObj:Tag = new Tag(p);

                   tagObj.occurences = tag_counter[p];

               }

           

           

           

          Alex Harui

          Flex SDK Developer

          Adobe Systems Inc.

          Blog: http://blogs.adobe.com/aharui

          • 2. Re: indexOf() function to search for object.<property> in object array
            axedre Level 1

            Hello,

            thanks very much for the reply, indeed this is what I needed.

            I think the code you wrote, though, is incomplete. I suppose you wrote the last "for" cycle to create an array of Tag objects to return to the caller of the harvest_tags function. So I guess two lines are missing:

             

            [...]
            var tag_array:Array = new Array();
            
            for (var p:String in tag_counter) {
                var tagObj:Tag = new Tag(p);
                tagObj.occurrences = tag_counter[p];
                tag_array.push(tagObj); // <-- this one
            }
            
            return tag_array; //<-- and of course this one
            

             

            That said, I have no particular constraints on the object type returned, so I guess I'll just change it to "Object" and return tag_counter, thus eliminating the need for a separate Tag class:

             

            private function harvest_tags(dt:DataTable):Object {
                var tag_counter:Object = new Object();
            
                for each(var site_feeds:Object in dt.data) {    //cycle through the Arrays
                    for each(var tag:String in site_feeds.t) {  //cycle through the tags
                        if(tag == '') continue;     //in case an empty tag is found, skip it
                        tag = tag.replace(',', ''); //strip commas
                        if (tag_counter[tag])
                            tag_counter[tag]++;
                        else
                            tag_counter[tag] = 1;
                     }
                 }
            
                 return tag_counter;
            }
            

             

            Of course, using a hashmap instead of an array makes me lose the possibility to sort it by occurrences descending. That shouldn't be a problem, though. Otherwise I'll just turn it into an array as you suggested and then sort the array.

            Thanks again, cheers,

             

            Andrea