Splitting a 2D array using some() , by date, avoiding duplicates. Just want 1 unique email, not row. Where am i wrong here?

StackOverflow https://stackoverflow.com/questions/21617453

Question

So title might seem a bit confusing, it might be as I'm confusing myself. I'm new to Javascript and learning it in order to use Google Spreadsheets better.

I've tried to write a script that will look at a Form responses sheet + a target sheet.

Target sheet will give script a date. Script will analyse data on Form responses based on that date. End goal is to produce a report.

At the moment I'm stuck on this. I can return the right amount of entries for that date. But it returns the whole row. Or i can return just emails, but it returns all 8 entries, not 2 All I want is unique emails for that date. 2

For my test date, I know there are 8 entries, 2 unique. But I'm getting mixed results. Also regarding the 2D array to 1,

I only want unique emails returned, but as far as I'm aware, Google-scripts ONLY deals with 2D arrays, So i think I have to return it as a 2D array anyways.

I got the some function after advice for a problem in a previous post, I'm just unsure about the mixed results now.

Perhaps I'm way wrong, but all help is appreciated. After feedback from previous posts, have tried to annotate as best I could, but I've only been learning Javascript for 2 months, so be gentle please, i bruise like a peach :) Thanks

function testByP() {
  var emailColumn =1; /* Which column has the email address, is unique per person */
  var dateColumn = 2; /* Which column has the the timestamp, duplicates are possible  */

  var target = "Agent By Date"; /* Sheet name that contains our lookup date in J14, and which we'll write the report to, watch this space it's not done yet */

  var ss = SpreadsheetApp.getActiveSpreadsheet(); /* Get the current spreadsheet */

  var sheet = ss.getSheetByName('Form Responses'); /* Sheet with data we are looking at. Really only Columns A,B are of interest in this case for now */
  var values = sheet.getDataRange().getValues(); /* get the values from the sheet we wish to query */
  var targetSheet = ss.getSheetByName(target); /* where we will evetually generate a report, but get date from to report on */

  var startDate = new Date (targetSheet.getRange(14,10).getValue()); /* Lets get that date we wish to report on */
  var archive = []; /* Where we will store unique emails found */

  var startGap = new Date().setTime(startDate.getTime()); /* Convert our date found to milliseconds since epoch to give us a start time/date */
  var endGap = new Date().setTime(startDate.getTime()+86400000); /* add a day to startGap in milliseconds, giving us our end point */

  for (var counter =  1; counter < values.length; counter++) {/* go through data, starting at row 2 as we have header */

  var testDate = new Date(values[counter][dateColumn -1]).getTime(); /* convert values time/date to epoch in milliseconds */


    if (testDate<endGap && testDate>startGap) {/* if it's between our times, ie on that day, do the following */


    if (archive.some(function (element, index, array) {
    return values[counter][emailColumn - 1] == element[emailColumn - 1]; /* This bit is MEANT to say, if the entry is in the archive array already, don't put it in */
        }))
    {
      continue; /* this is meant to say if data is in our archive then carry on */

    }
    archive.push(values[counter]);//* 2 entries added to archive array, no duplicates in email, but entire row added, when email is only needed.  << This is correct. There are 8 entries, only 2 unique. But it adds whole row, i just need email */
//    archive.push(values[counter][0]); // With this, 8 Added to archive, duplicates in email there where they shouldn't be. But it does add only email, no other data
    }


    }

  Logger.log(archive.length); /* For testing purposes */
  Logger.log(archive); /* For testing purposes */
  }
Was it helpful?

Solution

So this answer is not my own, but thanks to Bruce https://plus.google.com/u/0/+BruceMcpherson/posts

He's given me examples of manipulating 1d and 2d arrays in comparison to others.

here's how to create a 1d array of unique values

function uniqueValues() {
  var array = [1,2,2,3,4,1];
  var u = array.filter( function (v,i,a) {
    return a.indexOf(v) === i;
  });
  Logger.log (u);
}
// results
// [1.0, 2.0, 3.0, 4.0]

// and extend that to extract unique values from a particular column of a 2d arrray

function uniqueValues2D() {
  var array = [[1,"a",2,3,4,1],[1,"b",2,3,4,1],[1,"b",2,3,4,1]];
  var col = 1;

  var u = array.map( function (v) {
    return v[col];
  })
  .filter( function (v,i,a) {
    return a.indexOf(v) === i;
  });
  Logger.log (u);
}

// results
//  [a, b]

Part of my question, was that I wanted only to add one value to an array if it wasn't already there, I was currently adding a whole row. But it was unique :)

Again, Bruce came to the rescue with an explanation :

ok, so you want to add something to a second array from a first array if it does not already exist in the second array

function uniqueValuesAdd() {
  var values = [[1,"a",2,3,4,1],[1,"b",2,3,4,1],[1,"c",2,3,4,1]];
  var archive = ["x","b","y"];

  var col = 1;

  values.map( function (v) {
    return v[col];
  })
  .filter( function (v,i,a) {
    return a.indexOf(v) === i;
  })
  .forEach (function (v) {
      if (archive.indexOf(v) === -1) archive.push(v);
  });

  Logger.log (archive);
}

// result...
// [x, b, y, a, c]

Finally, in my original code I was using the some() function and results were unexpected.

Bruce's example and explanation was clear and concise again

.some() is exactly the same type of function as these others. It returns true or false depending on some criteria that you test on each element of the array. returning a true for any element will cause .some() to return true

function someTest(){
var test1 = [1,2,3,4].some ( function (v) {
 return v <1;

});
Logger.log(test1); 
// will be false and

var test2 =[1,2,3,4].some ( function (v) {
  return v === 3;
// will be true  
});
 Logger.log(test2); 
}

He's advised me and I can see some() might not be the best method to use for my needs.

The uniqueValuesAdd() & uniqueValues2D() gave me expected results on a sample of data. :) So I'm implementing these methods in my final solution.

Not sure if Bruce uses this forum, but full credit to him, just wished to share results. Can post up my edited code if anyone would find it useful, but the examples & explanations below put me right on track.

Cheers

OTHER TIPS

I wonder if you can use

if(archive.indexOf(values[counter][emailColumn - 1]) != -1)
  archive.push(values[counter][emailColumn - 1]);

then after everything is done do this to make it a 2d array

for(var i=0; i < archive.length; i++)
  archive[i] = [archive[i]];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top