Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have been wanting to become more OO. I develop a little in NetSuite and their APIs are in JS. I have the code below. Here is what is does.
1) search APIs does search on all transactions that are on the water.
2) Loops through all of the transactions and then searches for everyone of these transactions it does another search on them. The reason is because NetSuite's API governance only allows a 1000 lines with search APIs (this can be worked around other ways as well). Also want to do it this way because will be working in other logic that will make this way necessary.
3) Then pushes these values, item, quantity, created from record into three arrays.
4) The last loop loops through the three arrays, but then prints out the item and the created from transaction the number of times of the quantity value. This is because we are going to print these as labels for each item.
Now have been wanting to become more OO. I did another thing similar where I looped through object with keys and values. Thought that was neat. My question is how would you make this more OO. I have some ideas on what I would do but would like to hear some ideas.
1) Create some functions that will call step 3 and step 4. So each time it looped it called functions
2) I would like to do something with callbacks or promises. Might not be the use for them in this scenario, but
3) Push the items into an object then run forEach method on those objects.
So the question is how to make this more OO style with JavaScript.
// search APIs
filters = [];
filters[0] = new nlobjSearchFilter('location', null, 'anyof', ['23','25','20','24']);
filters[1] = new nlobjSearchFilter('mainline', null, 'is', 'true');
var columns = [];
columns[0] = new nlobjSearchColumn('tranid');
columns[1] = new nlobjSearchColumn('createdfrom');
var searchResults =[];
var searchResults = nlapiSearchRecord('itemreceipt', null, filters, columns);
tranId = [];
createdFrom = [];
quantity = [];
item = [];
data = '';
if(searchResults){
for (var i = 0; i < 5; i++){
// gets all internal IDs
var tranId = searchResults[i].getValue(columns[0]);
filtersLine = [];
filtersLine[0] = new nlobjSearchFilter('tranid', null, 'is', tranId);
filtersLine[1] = new nlobjSearchFilter('mainline', null, 'is', 'false');
var columnsLine = [];
columnsLine[0] = new nlobjSearchColumn('item');
columnsLine[1] = new nlobjSearchColumn('createdfrom');
columnsLine[2] = new nlobjSearchColumn('quantity');
var searchResultsLine =[];
var searchResultsLine = nlapiSearchRecord('itemreceipt', null, filtersLine, columnsLine);
for (var j = 0; j < searchResultsLine.length; j++){
item.push(searchResultsLine[j].getText(columnsLine[0]));
createdFrom.push(searchResultsLine[j].getText(columnsLine[1]));
quantity.push(searchResultsLine[j].getValue(columnsLine[2]));
for (var x = 0; x < quantity[j]; x++){
if(createdFrom[j] != 'undefined'){
data += item[j] + createdFrom[j] + '\n';
console.log(item[j] + ' ' + createdFrom[j].substring(16) + '\n');
}
}
}
}
}
You are running a search per each search result, that's gonna take a hit on your governance points. I checked the code and I see no real need to use that many searches. I have refactored the code to use more functions, also I nested the functions, this should make it more readable and scalable. I also added a couple of filters to avoid getting more data than what you need. Anyways, here's the code, you are welcome to optimize it further.
var itemsToProcess = getItemsToProcess();
var data = getDataString(itemsToProcess);
//**** HELPER FUNCTIONS ****//
function getItemsToProcess(){
// search APIs
var filters = [];
filters.push(new nlobjSearchFilter('location', null, 'anyof', ['23','25','20','24']));
filters.push(new nlobjSearchFilter('createdfrom', null, 'isnotempty'));
filters.push(new nlobjSearchFilter('quantity', null, 'greaterthan', 0)); //Filtering out items with no quantity
filters.push(new nlobjSearchFilter('mainline', null, 'is', 'F')); //Dont want to get any extra info
filters.push(new nlobjSearchFilter('shipping', null, 'is', 'F')); //Dont want to get any extra info
filters.push(new nlobjSearchFilter('cogs', null, 'is', 'F')); //Dont want to get any extra info
filters.push(new nlobjSearchFilter('taxline', null, 'is', 'F')); //Dont want to get any extra info
var columns = [];
columns.push(new nlobjSearchColumn('item'));
columns.push(new nlobjSearchColumn('createdfrom'));
columns.push(new nlobjSearchColumn('quantity'));
var searchResults = fullSearch('itemreceipt', filters, columns);
var rows = [];
for(var i in searchResults){
var result = {};
result.item = searchResults[i].getText(columnsLine[0]);
result.createdFrom = searchResults[i].getText(columnsLine[1]);
result.quantity = searchResults[i].getValue(columnsLine[2]);
rows.push(result);
}
return rows;
//**** HELPER FUNCTIONS ****//
function fullSearch(type, filters, columns){
var search = nlapiCreateSearch(type, filters, columns);
var resultset = search.runSearch();
var resultsets = [];
var returnSearchResults = [];
var searchid = 0;
var startdate, enddate, resultslice;
/* Grabs results first */
do {
resultslice = getResultSlice(resultset, searchid);
for (var rs in resultslice) {
returnSearchResults.push(resultslice[rs]);
searchid++;
}
} while (resultslice.length == 1000);
return returnSearchResults;
//*********** HELPER FUNCTION ***********/
function getResultSlice(resultset, searchid){
var resultslice = resultset.getResults(searchid, searchid + 1000);
return resultslice || [];
}
}
}
function getDataString(itemsToProcess){
var data = '';
for(var i in itemsToProcess){
data += printItem(itemsToProcess[i].item, itemsToProcess[i].createdFrom, itemsToProcess[i].quantity);
}
return data;
//**** HELPER FUNCTIONS ****//
function printItem(item, createdFrom, quantity){
var tempString = '';
for (var x = 0; x < quantity; x++){
console.log(item + ' ' + createdFrom.substring(16));
tempString += item + createdFrom + '\n';
}
return tempString;
}
}
Related
I have some data pulling from a sheet. I have created an array that is sorted by the 2nd column (SKU column) below is what is returned in the spreadsheet:
In this array would like to add a blank row when the SKU changes to make it easier to read. I wrote the following code:
function update(){
var mfgSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Order Info");
var purchaseLog = SpreadsheetApp.
openById("1KkR4jE1c00WuQpPrexW8f9BIq5vxl0fWaUGxbeYERsE").
getSheetByName("Order Details");
var orderSort = purchaseLog.getRange(3, 1, purchaseLog.getLastRow(), 15).getValues().
sort(function(r1,r2){
var a = r1[1];
var b = r2[1];
if(a>b){
return 1;
}else if (a<b){
return -1;}
return 0;
}).filter(function (item){if(item[1]!=""&&item[1]!="Purchase Order Link"){return true}})
.map(function(r){return [r[0],r[1],r[2],r[5],r[6],r[11],r[13],r[12],r[8]]});
var SKUs = orderSort.map(function(r){return r[1]})
var SKUList = [];
for (var i in SKUs) {
var SKU = SKUs[i];
var duplicate = false;
for (var j in SKUList) {
if (SKU === SKUList[j]) {
duplicate = true;
}
}
if (!duplicate) {
SKUList.push(SKU);
}
}
var finalArr = []
for(var i = 0; i <= SKUList.length-1; i++){
var element = orderSort.filter(function(item){if(item[1]===SKUList[i]){return true}});
finalArr.push(element);
finalArr.push([,,,,,,,,,]);
}
Logger.log(finalArr);
}
The code almost works, but I'm getting a weird 3d Array, and I'm afraid that my logic is very wrong. Photo of the log is also included. Anyone that could help me solve this problem, it would be greatly appreciated.
element is already a 2D array. By pushing it to another array, a 3D array is created. Use Array.concat instead:
finalArr = finalArr.concat(element);//instead of finalArr.push(element);
I'm wanting to remove duplicate values from the array tabData produced by the script below.
I've found numerous posts here that mention "removing duplicates from array", but don't seem to be relevant to my exact goal.
I've tried filter, I've tried using this answer and adjusting the variables to fit my script, but it did not remove the duplicates.
Surely there is a simple function that does exactly what I'm looking for, I'm just not finding it.
function getTabArray() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var version = ss.getRangeByName("version").getValue().toString();
var updateTabsName = "updateTabs";
var updateTabsSheet = ss.getSheetByName(updateTabsName);
var tabDataRows = updateTabsSheet.getLastRow();
var tabDataCols = updateTabsSheet.getMaxColumns() - 1;
var tabDataRange = updateTabsSheet.getRange(1, 2, tabDataRows, tabDataCols);
var tabData = tabDataRange.getValues(); // <-- REMOVE DUPLICATES
for (var i = 0; i < tabData.length; i++) {
if (tabData[0][i] != "" && tabData[0][i] > version) {
for (var j = 0; j < tabData.length; j++) {
if (tabData[j][i] != "" && j > 0) {
Logger.log("tabData[j][i] = " + tabData[j][i]); // tabData[j][i] = all values in column
}
}
}
}
}
This is the array it currently produces:
2.20200514.2,2.20200514.0,2.20200513.2,2.20200513.1,2.20200513.0,2.20200512.0,1.20200405.1,,tabDefinitions,Sheet6,Sheet6,changeLog,Sheet6,Index,,,,Sheet7,,Sheet7,settings,,,,Sheet8,,Sheet8,tabDefinitions,,,,,,,changeLog,,,,,,,updateTabs
I want to remove all duplicates (Sheet6, Sheet7, Sheet8, etc.) from the array.
EDIT:
After one more search, I found this answer which contains exactly what was answered below, but when I use any method in that answer, I still get all duplicates. Not sure what I'm doing wrong or not doing right.
var unique = tabData.filter((v, i, a) => a.indexOf(v) === i);
EDIT 2:
I realized my array was not actually "flat", so I added var tabData = tabDataRange.getValues().flat(); and now everything works!
You can use ES6 Set() function to remove the duplicates
const newArray = [...new Set(arrayWithDuplicates)];
EDIT - code to calculate refill_playlist_len included
I have a function in Javascript that deletes a row of an HTML table and populates it again with values from arrays.
Within this deleteRow function, I have a for loop which loops through a string and assigns parts of the strings to different variables and tries to push them onto arrays.
Without the for loop, it works fine (i.e. when I just index manually) but for some reason when I place it in a for loop, the values aren't pushed onto the arrays. The values themselves print fine on each iteration they just aren't added to the array.
Refill_playlist_len is the count of the Django Queryset (30).
var refill_playlist_len = '{{ playlist.count }}';
var artist_Arr = [];
var track_Arr = [];
var track_id_Arr = [];
var album_Arr = [];
var artist_name;
var track_name;
var track_id;
var album_name;
for (var i = 0; i < refill_playlist_len; i++) {
var searchStr = refill_playlist[i];
console.log(searchStr);
console.log(typeof searchStr);
console.log(typeof refill_playlist);
//grab variables
artist_name = searchStr.match(new RegExp("artist_name:" + "(.*)" + ", album_name:"));
console.log(artist_name[1]);
artist_Arr.push(artist_name[1]);
track_name = searchStr.match(new RegExp("track_name:" + "(.*)" + ", acousticness:"));
console.log(track_name[1]);
track_Arr.push(track_name[1]);
track_id = searchStr.match(new RegExp("track_id:" + "(.*)" + ", track_name:"));
console.log(track_id[1]);
track_id_Arr.push(track_id[1]);
album_name = searchStr.match(new RegExp("album_name:" + "(.*)" + ", track_number:"));
console.log(album_name[1]);
album_Arr.push(album_name[1]);
}
The console logs are in the image below. You can see part of the 'searchStr' printed, along with the data types, artist name, track IDs, etc but for some reason, it says that 'searchStr' is undefined?
Console
I'm quite new to Javascript so my apologies if there is something basic I'm forgetting.
Multiple issues with code. Please clean up code. Sample is given below.
function find(refill_playlist) {
const refill_playlist_len = refill_playlist.length
let artist_Arr = []
let track_id_Arr = []
let track_Arr = []
let album_Arr = []
for (i = 0; i < refill_playlist_len; i++) {
var searchStr = refill_playlist[i];
if(!searchStr) continue;
//grab variables
artist_name = searchStr.match(/artist_name:(.*), album_name:/);
artist_name && artist_Arr.push(artist_name[1]);
track_name = searchStr.match(/track_name:(.*), acousticness:/);
track_name && track_Arr.push(track_name[1]);
track_id = searchStr.match(/track_id:(.*), track_name:/);
track_id && track_id_Arr.push(track_id[1]);
album_name = searchStr.match(/album_name:(.*), track_number:/);
album_name && album_Arr.push(album_name[1]);
}
console.log(artist_Arr)
console.log(track_id_Arr)
console.log(track_Arr)
console.log(album_Arr)
}
find(
[
`
artist_name: test, album_name:
`,
null
]
)
I currently have a list with two columns. The first column is student name, and the second column is the number of points they have.
I imported this list from multiple spreadsheets so there were many duplicates on the names of the students. I am able to remove the duplicates, but I want to keep a tally on the total points they have. For example:
Amy 10
Bob 9
Carol 15
Amy 12
would turn into:
Amy 22
Bob 9
Carol 15
This is what I have so far:
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B1000").getValues();
var newData = new Array();
var k = 0
var finallist = []
for(i in data){
k++;
var row = data[i];
var duplicate = false;
for(j in newData){
if(row[0] == newData[j][0]){
duplicate = true;
var storedHour = sheet.getRange("B"+k).getValue();
var position = finallist.indexOf(row[0]);
var originalCell = sheet.getRange("B"+(position+1));
var originalHour = originalCell.getValue();
originalCell.setValue(originalHour + storedHour);
sheet.getRange(k,2).setValue("")
sheet.getRange(k,1).setValue("")
}
}
if(!duplicate){
newData.push(row);
finallist.push(row[0])
}
}
}
The problem I'm having is that we have a really large data sample and I'm afraid it may run over Google's 5 minute maximum execution time. Is there another more efficient way to achieve my goal?
Your code is running slow because Spreadsheets API methods (like getRange) are time consuming and much slower then other JavaScript code.
Here is optimized function with reduced number of such Spreadsheets API calls:
function calcNumbers()
{
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var lastRow = sheet.getLastRow();
var dataRange = sheet.getRange(2, 1, lastRow-1, 2);
var data = dataRange.getValues();
var pointsByName = {};
for (var i = 0; i < data.length; i++)
{
var row = data[i];
var curName = row[0];
var curNumber = row[1];
// empty name
if (!curName.trim())
{
continue;
}
// if name found first time, save it to object
if (!pointsByName[curName])
{
pointsByName[curName] = Number(curNumber);
}
// if duplicate, sum numbers
else
{
pointsByName[curName] += curNumber;
}
}
// prepare data for output
var outputData = Object.keys(pointsByName).map(function(name){
return [name, pointsByName[name]];
});
// clear old data
dataRange.clearContent();
// write calculated data
var newDataRange = sheet.getRange(2, 1, outputData.length, 2);
newDataRange.setValues(outputData);
}
Sorting before comparing allows looking at the next item only instead of all items for each iteration. A spillover benefit is finallist result is alphabatized. Execution time reduction significant.
function sumDups() {
var target = SpreadsheetApp.getActiveSpreadsheet();
var sheet = target.getSheetByName("Sheet2");
var data = sheet.getRange("A2:B" + sheet.getLastRow()).getValues().sort();
var finallist = [];
for(var i = 0; i<= data.length - 1; i++){
var hours = data[i][1];
while((i < data.length - 1) && (data[i][0] == data[i+1][0])) {
hours += data[i+1][1];
i++;
};
finallist.push([data[i][0], hours]);
};
Logger.log(finallist);
}
Edit: the simple data structure with the name being in the first column allows this to work. For anything more complex understanding and applying the methods shown in #Kos's answer is preferable
i been reading for hours trying to make this work but i dont have much knowledge to do it.
I have this js code:
var username=$(this).attr("username");
It pull a list of users f.e (admin, test1, test2, test3)
and i needs to split it into another var like this:
var members = [
['admin'],
['test1'],
['test2'],
['test3'],
];
I tried a lot of codes but i cant make it work, thanks in advance!
To get an array of usernames:
var username = $(this).attr("username");
var members = username.split(',');
To get exactly what you've suggested you want (an array of arrays? - I don't think this is actually what you want):
var username = $(this).attr("username");
var membersArr = username.split(',');
var members = new Array();
for (var i = 0; i < membersArr.length; i++)
{
members[i] = [ membersArr[i] ];
}
To get "[test1]", "[test2]" etc:
var username = $(this).attr("username");
var members = username.split(',');
for (var i = 0; i < members.length; i++)
{
members[i] = '[' + members[i] + ']';
}
Update
To get the array of arrays,
var username=$(this).attr("username");
var membersArray= username.split(' ').map(function(username){
return [username];
})
//[["admin"],["test"],["test1"],["test2"]]
I've added a fiddle here