2

I am writing a script for Google Spreadsheet.

Array 1 have a series of names (more than 50 different names)

John, Pete, Paul, ... Michael

Array 2 is a series of repeated names from those given 50 (more than 10K in total)

Paul, Michael, Pete, John, Paul, Paul, Pete, Michael, Paul, Michael,... Michael

How can I make another Array with the number of occurrences (Array 2) for every given name in Array 1?

Sorting is not possible. Therefore, Array 3 should take into consideration the order of Array 1. In this case, for instance:

1, 2, 3,... 4

I have seen & proved how to make it if order is not important (from Array 2, Array 1 is created with unique names and Array 3 contains their occurrences --> Counting the occurrences of JavaScript array elements), but all my approaches seem to don't work. So far, I have this:

var namesCountArray = [];
namesArray = ss.getRange("CU3:CU" + rows + "").getValues();
namesSerieArray = ss.getRange("DF3:DF" + rows + "").getValues();

for(var i=0; i< namesArray.length; i++) {
    var count = 0;
    for(var i = 0; i < namesSerieArray.length; ++i) {
        if(namesSerieArray[i] == namesArray[i])
            count++;
    }
    namesCountArray.push([count]);
}
ss.getRange("DB3").setValue(namesCountArray);
Community
  • 1
  • 1
agustin
  • 1,311
  • 20
  • 42
  • do you really need to do this with a script? you may simply use a counta formula or for a more complicated analysis a pivot table? – Harold Sep 30 '14 at 15:46

3 Answers3

3

You need to use a different variable in the second for loop or take it out all together:

for(var i=0; i< namesArray.length; i++) {
  var count = 0;
  for(var i = 0; i < namesSerieArray.length; ++i){
  if(namesSerieArray[i] == namesArray[i])
    count++;
  }

You're going through and checking each pair 1 with 1, 2 with 2, 3 with 3 only. You should do separate variables if you want to check each index pair (1 with 1, 1 with 2 ...). Ex:

for(var i=0; i< namesArray.length; i++) {
  var count = 0;
  for(var j = 0; j < namesSerieArray.length; j++){
  if(namesSerieArray[i] == namesArray[j])
    count++;
  }
Charles B.
  • 193
  • 1
  • 7
  • Good eye. I totally missed that `i` was used for both loops. The `count` is being pushed as `[count]`, so that may be an issue too if that wrapping array wasn't wanted. –  Sep 29 '14 at 15:09
  • Right, he may intend for it to be that way. Not sure. However the loop is actually closed. The `if` statement doesn't use curly braces. :) –  Sep 29 '14 at 15:16
  • Yeah, I noticed that afterwards and deleted my comment because I was being a goof. But yeah, I didn't know exactly what all he wanted so I left it alone. xP – Charles B. Sep 29 '14 at 15:21
  • @CharlesB., thx. You was not being goof at all (I red the original msg but couldn't answer until yet). I have to admit my ignorance. Today is my first day using arrays, and one month ago I didn't have any experience, so it's possible that the original code was totally false. @squint, I'm using `[count]` because Google App Scripts requires it. At least with other Arrays have worked, because without `[]` it always says _Cannot convert Array to Objec_. However, as my code is originally buggy, it maybe doesn't need the brackets. – agustin Sep 29 '14 at 20:47
  • The problem is, however, that I cannot make it work. Do you think it's because Google App Scripts generates 2-Dim Arrays when calling `namesArray = ss.getRange("CU3:CU" + rows + "").getValues();`? If I print this array in one cell I get something like this `[[Pete], [John], [Paul],... [Michael]]` instead of `["Pete", "John", "Paul",... "Michael"]`. – agustin Sep 29 '14 at 20:52
  • Yes it is because you're getting a 2D array. You want to compare the values of the arrays, not the arrays themselves. So instead of `nameSerieArray[i] == namesArray[j]` try `nameSerieArray[i][0] == namesArray[j][0]`. So `nameSerieArray[0]` corresponds to `[Pete]` (an array with one element, `"Pete"`), however `nameSerieArray[0][0]` corresponds to `"Pete"`. – Charles B. Sep 30 '14 at 20:50
3
// names we want to find
var names = ["john", "pete", "paul"];

// target list of names.
// john, pete, paul appear 2x
var target = ["john", "pete", "jack", "cindy", "thomas", "paul", "john", "pete", "paul"];

function finder(search, target) {
    return search.map(function (val) {
        return target.filter(function (e) {
            return val === e;
        }).length;
    });
}

finder(names, target);
// => [2, 2, 2]

Demo: http://jsfiddle.net/austinpray/v14o38ta/

Austin Pray
  • 4,926
  • 2
  • 22
  • 30
2

Walk through the array2 and build an object with every key as a name and the value as the number of its occurences.

e.g.

var array2 = ["Paul", "Michael", "Pete", ... /* 47 more names */ ];
var occurences = {};

for (var i = 0, l = array2.length; i++; i<l) {
   if (occurences[array2[i]] === undefined) {
     occurences[array2[i]] = 1;
   }
   else {
     occurences[array2[i]]++;
   }
}

then walk the first array, check if the name is in the object occurences and push its value in a new array, like so

var array1 = ["Paul", "Michael", "Pete", "John", "Steve", "Bill" ];
var array1Frequency = [];

for (var i = 0, l = array1.length; i++; i<l) {
    array1Frequency.push(occurences[array1[i]] || 0)
}
Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177