Google Apps Script: Comparing Arrays for Unique Values - javascript
I'm working from the solution provided HERE to compare two arrays. The example provided returns values found in both arrays to Array1 (same) and values only found on one or the other two Array2 (diff).
ISSUE: When I apply it to my own script, valuesDATA returns nothing and valuesCheckSeeding returns ALL values from both arrays
DESIRED RESULT: I have two arrays that I'd either like to create a third out of, or only select values from the first array, valuesDATA which are NOT present in the second, valuesCheckSeeding. Using the solution above, I was trying to have all values not found in valuesCheckSeeding AND valuesDATA pushed to valuesDATA.
SAMPLE OF valuesDATA: "U09 F
Harford FC Hill/Healey - A
MD
CMSA Girls Saturday U09 A/B North
Premier - Top
TID0118"
What am I doing wrong? I tinkered with changing matchfound==false and matchfound=true in the loop, but that still didn't give me the desired result.
MOST RELEVANT SNIPPET
var matchfound = false;
for (var i = 0; i < valuesDATA.length; i++) {
matchfound=false;
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i] == valuesCheckSeeding[j]) {
valuesCheckSeeding.splice(j, 1);
matchfound=true;
continue;
}
}
if (matchfound==false) {
valuesCheckSeeding.push(valuesDATA[i]);
valuesDATA.splice(i, 1);
i=i-1;
}
}
WORKIG SCRIPT EDITED FROM COMMENTS/ANSWERS BELOW
//UPDATE SEEDING SHEET
function updateSeedingSheet() {
var today = Utilities.formatDate(new Date(),Session.getScriptTimeZone(), "MM/dd/yyyy hh:mm a");
//INPUT SHEET INFO
var inputCurrentRow = 4;
var inputCurrentColumn = 20;
var inputNumRows = 1000;
var inputNumColumns =1;
var ssInput = SpreadsheetApp.openById('1Wzg2BklQb6sOZzeC0OEvQ7s7gIQ07sXygEtC0CSGOh4');
var sheetDATA = ssInput.getSheetByName('DATAREF');
var rangeDATA = sheetDATA.getRange(inputCurrentRow, inputCurrentColumn, inputNumRows, inputNumColumns);
var valuesDATA = rangeDATA.getValues();
//SEEDING SHEET INFO
var seedingCurrentRow = 4;
var seedingCurrentColumn = 1;
var seedingNumRows = 1000;
var seedingNumColumns = 1;
var ssSeeding = SpreadsheetApp.openById('1DuCHeZ3zba-nHq-7vYTrylncPGqcA1J9jNyW9DaS3mU');
var sheetSeeding = ssSeeding.getSheetByName('Seeding');
var rangeCheckSeeding = sheetSeeding.getRange(4, 102, 1000, 1);
var columnToClear = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, seedingNumRows, seedingNumColumns);
var valuesCheckSeeding = rangeCheckSeeding.getValues();
//METHOD TO FILTER
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);
Logger.log(filteredArr.length);
var rangeSeeding = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, filteredArr.length, seedingNumColumns);
sheetSeeding.getRange('A1').setValue(today);
columnToClear.clearContent();
rangeSeeding.setValues(filteredArr);
/*
//ALTERNATIVE METHOD USING LOOPS
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log("VALUES DATA:" + valuesDATA);
Logger.log("VALUES CHECK SEEDING: " + valuesCheckSeeding);
//sheetSeeding.getRange('A1').setValue(today);
//rangeSeeding.clearContent();
//rangeSeeding.setValues(valuesDATA); //INCORRECT RANGE HEIGHT, WAS 71 BUT SHOULD BE 1000 - Is splice affecting this?
*/
}//END FUNCTION
V8(ES2016 update):
You can use newer and efficient set class
const array1 = [[1],[2],[3]],
array2 = [[1],[3],[4]],
set = new Set(array2.flat())
console.info(array1.filter(e => !set.has(e[0])))
//expected output [[2]]
You're checking a 2D array. You'd need to use [i][0] and [j][0]
You can try only splicing valuesDATA
Try
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log(valuesDATA);
Alternatively, try
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);
Related
How create new array from looping value date from object?
i have object with array of names koktelData.strIngredient1 to 15 and values. I want loop that array and create new array with all values from koktelData.strIngredient1 to 15. I tray something like this but new array have 15 elements undefined1 to undefined15. var sastojak = koktelData.strIngredient; let sastojci = []; for (let i = 1; i < 16; i++) { var sastojak_niz = koktelData.strIngredient + [i]; const sastajak = sastojci.push(sastojak_niz); } console.log(sastojci);
try this out let sastojci = []; for (let i = 1, j = 0; i < 16; i++, j++) { sastojci[j] = koktelData.strIngredient + i } console.log(sastojci); If coktelData.strIngredient is an array then it should start at 0. And this is how it should work. If not then contact me and add koktelData.strIngredient to the question so I can test it. If koktelData.strIngredient is an String then pls show format
How to assign array A values to array B in JS/appscript?
I am developing some Stock tools with AppScript and now I dont know why I cannot assign the array A values to array B. Could someone help me ? I want to copy the values_array [l][0] -> dataArray [l][0] Could you please give me the solution please? //Filled up the array for MACD // var dataArray = [["Stock","Date","Close Price","EMA12","EMA26","DIF","Signal"]]; var dataArray = []; var accumulationEMA12 = 0; for (var l = 0; l < values_array.length - 1; l++) // Get the previous day EMA12 { var temp = values_array[l][5]; // var accumulationEMA12 = accumulationEMA12 + values_array[l][5]; var accumulationEMA12 = accumulationEMA12 + temp; dataArray[l][0] = values_array[l][0]; // Fill Up the Stock No. <-Here dataArray[l][1] = values_array[l][1]; // Fill UP the Date <-Here if (l < 11) //if the dataset is < 12 rows or < 26 rows, calculate the average instead of EMA { } } //Filled up the array for MACD // var dataArray = [["Stock","Date","Close Price","EMA12","EMA26","DIF","Signal"]]; var dataArray = []; var accumulationEMA12 = 0; for(var l = 0; l< values_array.length-1; l++) // Get the previous day EMA12 { var temp = values_array[l][5]; // var accumulationEMA12 = accumulationEMA12 + values_array[l][5]; var accumulationEMA12 = accumulationEMA12 + temp; dataArray[l][0] = values_array[l][0]; // Fill Up the Stock No. dataArray[l][1] = values_array[l][1]; // Fill UP the Date if(l < 11) //if the dataset is < 12 rows or < 26 rows, calculate the average instead of EMA { } } Values_array here
I think you are getting error at the line dataArray[l][0] = values_array[l][0]; Because, no where I see you have initiated dataArray[l]. In your code, dataArray[l] is undefined, so when you try to do something like dataArray[l][1], you are essentially doing undefined[1] which will throw such type error Uncaught TypeError: Cannot read property '1' of undefined So what you need to do is, make sure dataArray[l] is an array itself. Something like this var dataArray = []; for (var l = 0; l < values_array.length; l++) { // make sure dataArray[l] exists dataArray[l] = []; // do your operations dataArray[l][0] = values_array[l][0]; dataArray[l][1] = values_array[l][1]; // other code. } Although, I would suggest using modern JS language features, like const dataArray = []; values_array.forEach((val, index)=> { // notice that we are assigning a new array to dataArray[index] dataArray[index] = [ val[0], val[1], ]; // do other operations like if (index < 11) { // do stuff } }); Hope it helps.
How to programmatically create 3D array that increments to a defined number, resets to zero, and increments again?
Starting with this initial 2D array: var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]]; I need to create this 3D array programmatically: var fullArray = [ [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]], [[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]], [[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]], [[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]], [[6,7],[3,4],[1,2],[5,6],[2,3],[6,7]], [[0,1],[4,5],[2,3],[6,7],[3,4],[0,1]], [[1,2],[5,6],[3,4],[0,1],[4,5],[1,2]], [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]], [[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]], [[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]], [[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]] ]; See the pattern? On each pair, the [0] position should increment to 6 (from any starting number <= 6) and then reset to 0 and then continue incrementing. Similarly, the [1] position should increment to 7 (from any starting number <= 7) and then reset to 1 and then continue incrementing. In this example, there are 10 2D arrays contained in the fullArray. However, I need this number to be a variable. Something like this: var numberOf2DArraysInFullArray = 12; Furthermore, the initial array should be flexible so that initialArray values can be rearranged like this (but with the same iteration follow-through rules stated above): var initialArray = [[6,7],[2,3],[5,6],[4,5],[1,2],[6,7]]; Any thoughts on how to programmatically create this structure? Stumped on how to gracefully pull this off. Feedback greatly appreciated!
Here's a solution, I've separated the methods, and I made it so if instead of pairs it's an N size array and you want the [2] to increase up to 8 and reset to 2, if that's not needed you can simplify the of the loop for(var j = 0; j < innerArray.length; j++) var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]]; var create3DArray = function(array, size){ var newArray = [initialArray]; for(var i = 0; i < size; i++) { newArray.push(getNextArrayRow(newArray[i])); } return newArray; } var getNextArrayRow = function(array){ var nextRow = []; for(var i = 0; i < array.length; i++) { var innerArray = array[i]; var nextElement = []; for(var j = 0; j < innerArray.length; j++) { var value = (innerArray[j] + 1) % (7 + j); value = value === 0 ? j : value; nextElement.push(value); } nextRow.push(nextElement); } return nextRow; } console.log(create3DArray(initialArray,3)); Note, the results from running the snippet are a bit difficult to read...
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]]; var numOfArrays = 10; // get a range array [0, 1, 2, ...] var range = []; for (var i = 0; i < numOfArrays; i++) { range.push(i); } var result = range.reduce(function(prev, index) { if (index == 0) { return prev; } prev.push(transformArray(prev[index - 1])); return prev; }, [initialArray]) console.log(result); function transformArray(arr) { return arr.map(transformSubArray) } function transformSubArray(arr) { return arr.map(function(val) { return val == 7 ? 0 : val + 1; }) } Here's a pretty simple functional-ish implementation
Dynamic Array Value Count
Similar to this question - Array value count javascript How would I go about doing this, except with dynamic values? var counts = [] var dates= [ "28/05/2013", "27/05/2013", "28/05/2013", "26/05/2013", "28/05/2013" ]; How would I get a count of the duplicated array values? So how many 28/05/2013 etc. The dates are all dynamic, so I can't just search for set values. I just can't get my head around how I would do this. I may just scrap this idea, and get the value count from the last 10 days or something... but this may come in handy later(if it is even possible to do this).
This will do it: var counts = {}; for (var i=0; i<dates.length; i++) if (dates[i] in counts) counts[dates[i]]++; else counts[dates[i]] = 1; The result will be > counts { "28/05/2013": 3, "27/05/2013": 1, "26/05/2013": 1 }
Make counts an object to perform duplicate detection in constant time. var counts = {} for (var i = 0; i < dates.length; i++) { var date = dates[i]; if (counts[date] === undefined) { counts[date] = 0; } counts[date] += 1; } console.log(counts);
Try like this Updated var dates= [ "28/05/2013", "27/05/2013", "28/05/2013", "26/05/2013", "28/05/2013" ]; var findStr = "28/05/2013"; var indexs = dates.indexOf(findStr,0),count=0; for (var i=0;i< dates.length;i++){ if (indexs >= 0){ indexs = dates.indexOf(findStr,indexs + 1); count++; } } alert(count); See Demo
Handling multidimentional array in java script is not working
function split(str) { var array = str.split(';'); var test[][] = new Array(); for(var i = 0; i < array.length; i++) { var arr = array[i].split(','); for(var j = 0; j < arr.length; j++) { test[i][j]=arr[j]; } } } onchange="split('1,2,3;4,5,6;7,8,9;a,b,c;d,e,f;g,h,i')" it was not working. i need to split this string to 6*3 multi dimentional array
var array[][] = new Array() is not valid syntax for declaring arrays. Javascript arrays are one dimensional leaving you to nest them. Which means you need to insert a new array into each slot yourself before you can start appending to it. Like this: http://jsfiddle.net/Squeegy/ShWGB/ function split(str) { var lines = str.split(';'); var test = []; for(var i = 0; i < lines.length; i++) { if (typeof test[i] === 'undefined') { test[i] = []; } var line = lines[i].split(','); for(var j = 0; j < line.length; j++) { test[i][j] = line[j]; } } return test; } console.log(split('a,b,c;d,e,f'));
var test[][] is an invalid javascript syntax. To create a 2D array, which is an array of array, just declare your array and push arrays into it. Something like this: var myArr = new Array(10); for (var i = 0; i < 10; i++) { myArr[i] = new Array(20); } I'll let you apply this to your problem. Also, I don't like the name of your function, try to use something different from the standards, to avoid confusion when you read your code days or months from now.
function split(str) { var array = str.split(';'), length = array.length; for (var i = 0; i < length; i++) array[i] = array[i].split(','); return array; } Here's the fiddle: http://jsfiddle.net/AbXNk/
var str='1,2,3;4,5,6;7,8,9;a,b,c;d,e,f;g,h,i'; var arr=str.split(";"); for(var i=0;i<arr.length;i++)arr[i]=arr[i].split(","); Now arr is an array with 6 elements and each element contain array with 3 elements. Accessing element: alert(arr[4][2]); // letter "f" displayed