Calculate values only for specific values - javascript

I have function that calculates difference between current and previous rows
Here it is
function distanceDifference() {
var rowsDistance = $('#tbody tr');
for (j = 1; j < rowsDistance.length; j++) {
// Get the rows
var previousDistanceRow = rowsDistance.eq(j - 1);
var currentDistanceRow = rowsDistance.eq(j);
var previousDistance = previousDistanceRow.find('td').eq(5).text();
var currentDistance = currentDistanceRow.find('td').eq(5).text();
//alert(previousDistance);
var difference = currentDistance - previousDistance;
//alert(difference);
currentDistanceRow.find('td').eq(6).text(difference);
}
}
It works well for all values
But I have column
<td id="dataType">#data.Datatype</td>
Value of it can be 0,1,2
I need to calculate difference only if it ===2
I try to do it like this
function distanceDifference() {
var rowsDistance = $('#tbody tr');
for (j = 1; j < rowsDistance.length; j++) {
var value = $('#dataType').text();
if (value === 2) {
// Get the rows
var previousDistanceRow = rowsDistance.eq(j - 1);
var currentDistanceRow = rowsDistance.eq(j);
var previousDistance = previousDistanceRow.find('td').eq(5).text();
var currentDistance = currentDistanceRow.find('td').eq(5).text();
//alert(previousDistance);
var difference = currentDistance - previousDistance;
//alert(difference);
currentDistanceRow.find('td').eq(6).text(difference);
}
}
}
but it not works. How I need to write code correctly?

Use if (value == 2) instead of if (value === 2).
Because equality operator === compares also the operands data types.
But the data type for the value '2' is string and you comparing with integer 2
Operator == will compare only value 2 == 2, without comparing the operands data types!

Even though a non-strict comparison would work it is - in my opinion - better practice to validate and convert user input to a specific data type.
So if you expect the users input to be an integer, use this
var value = parseInt( $('#dataType').text(), 10 );
If you expect it to be a number with a floating point, use this instead:
var value = parseFloat( $('#dataType').text() )
Then you can use a strict comparison like you already did.
But always validate if the user input has the right format.

So trouble was in that I get only first value from column
Here is valid code
function distanceDifference() {
var rowsDistance = $('#tbody tr');
for (j = 1; j < rowsDistance.length; j++) {
//var value = parseInt($('.dataType ').html());
var test = $('.dataType');
if (parseInt($(test[j]).html()) === 2) {
// Get the rows
var previousDistanceRow = rowsDistance.eq(j - 1);
var currentDistanceRow = rowsDistance.eq(j);
var previousDistance = previousDistanceRow.find('td').eq(5).text();
var currentDistance = currentDistanceRow.find('td').eq(5).text();
var difference = currentDistance - previousDistance;
currentDistanceRow.find('td').eq(6).text(difference);
}
}
}

Related

Netsuite Javascript Grab Last Array Value

So I found some info on this site on how to go about grabbing the value of the last index of an array. I have an Array that is of an unknown length. It builds based on a search of results. For example:
var custid = nlapiGetFieldValue('entity');
var custRecord = nlapiLoadRecord('customer', custid);
var itemPriceLineCount = custRecord.getLineItemCount('itempricing');
for (var i = 1; i <= itemPriceLineCount; i++) {
var priceItemId = [];
priceItemId = custRecord.getLineItemValue('itempricing', 'item', i);
if (priceItemId == itemId) {
var histCol = [];
histCol[0] = new nlobjSearchColumn('entity');
histCol[1] = new nlobjSearchColumn('totalcostestimate');
histCol[2] = new nlobjSearchColumn('tranid');
histCol[3] = new nlobjSearchColumn('trandate');
var histFilter = [];
histFilter[0] = new nlobjSearchFilter('entity', null, 'is', custid);
histFilter[1] = new nlobjSearchFilter('item', null, 'is', itemId);
var histSearch = nlapiSearchRecord('invoice', null, histFilter, histCol);
for (var h = 0; h <= histSearch.length; h++) {
var itemRate = new Array();
var histSearchResult = histSearch[h];
itemRate = histSearchResult.getValue('totalcostestimate');
}
}
}
Now when I use:
var last_element = itemRate[itemRate.length - 1];
It gives me the number of digits/placeholders in each element of the array. So as per my example I know my array holds the values of .00 and 31.24 because I put them there for a test. So last_element will result in 3 and 5. How can I grab the value 31.24 or the last element period? I need the value not the number of digits.
var itemRate = new Array();// Not sure what you intend to do with this array
var histSearchResult = histSearch[h];
itemRate = histSearchResult.getValue('totalcostestimate'); // but note `itemRate` is no more an array here. Its a variable having the value of `totalcostestimate` in string format
Now coming to your use case
/* you're trying to get the length of the string value and subtracting -1 from it.
So its very obvious to get those number of digits */
var last_element = itemRate[itemRate.length - 1]; // returns you that index value of the string
If you want to get the last array value of your search i.e histSearch
You may want to do something like this
var last_element = histSearch[histSearch.length-1].getValue('totalcostestimate');
As a side note it is always recommended to validate the returning value from a saved search result. Because on a successful search it returns you an array object on the other hand if no result founds it'll return you null.
//likely to get an error saying can't find length from null
for (var h = 0; h <= histSearch.length; h++) {
}
You can use something like this
// Never enter into the loop if it is null
for (var h = 0; histSearch!=null && h <= histSearch.length; h++) {
}

Javascript: reducing down to one number

So I need to take a date and convert it into one single number by adding up each digit, and when the sum exceeds 10, I need to add up the two digits. For the code below, I have 12/5/2000, which is 12+5+2000 = 2017. So 2+0+1+7 = 10 & 1+0 = 1. I get it down to one number and it works in Firebug (output of 1). However, it is not working in a coding test environment I am trying to use, so I suspect something is wrong. I know the code below is sloppy, so any ideas or help reformatting the code would be helpful! (Note: I am thinking it has to be a function embedded in a function, but haven't been able to get it to work yet.)
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
solution("2000, December 5");
You can just use a recursive function call
function numReduce(numArr){
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend","Reducing: "+numArr.join(","));
//Using the array's reduce method to add up each number
var total = numArr.reduce(function(a,b){return (+a)+(+b);});
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend",": Total: "+total+"<br>");
if(total >= 10){
//Recursive call to numReduce if needed,
//convert the number to a string and then split so
//we will have an array of numbers
return numReduce((""+total).split(""));
}
return total;
}
function reduceDate(dateStr){
var arrayDate = new Date(dateStr);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
return numReduce([d,m+1,y]);
}
alert( reduceDate("2000, December 5") );
<div id="log"></div>
If this is your final code your function is not outputting anything. Try this:
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
alert(solution("2000, December 5"));
It will alert the result in a dialog.

Validation for numeric data Javascript

I'm writing a program in Javascript that separates even and odd numbers, puts them into an array, adds the sum of numbers, and finds the average.
I'm having an issue not allowing zeros not to count. Because its adding to the array, and when the user types in 6+6, sum is 12, average is calculating to 4 because of the extra 0 in the array.
Is there anyway to not allow the zeros to count? Here is what I have so far..
var evenarray = [];
var oddarray = [];
var avgEven = 0;
var avgOdd = 0;
var isValid;
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
//alert("even");
}
if(numbers % 2 !== 0)
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
//alert("odd");
}
//if(isNaN(numbers)){
//alert("Only numeric data only");
//}
}
while(numbers !== "");
Just do nothing when the number is actually 0:
if (numbers == 0)
{
}
else if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
}
else // only odds remain
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
}
You can do :
if(numbers % 2 == 0 && numbers !=0) ...
if(numbers % 2 != 0 && numbers !=0) ...
so that you don't do anything when numbers == 0;
It's a little strange to call your variable numbers instead of number.
your function should be,
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers !=0 && !isNaN(numbers))
(numbers %2 == 0)? (evenarray.push(parseInt(numbers))) : (oddarray.push(parseInt(numbers)));
}while(numbers !== "");
for(var i = 0; i < evenarray.length; i++)
sumEven += evenarray[i];
for(var i = 0; i < oddarray.length; i++)
sumOdd += oddarray[i];
avgEven = sumEven / evenarray.length;
avgOdd = sumOdd / oddarray.length;
document.getElementById("even").innerHTML = evenarray.toString();
document.getElementById("sumEvenTotal").innerHTML = sumEven.toString(); //displays sum of even numbers.
document.getElementById("averageOdd").innerHTML = avgOdd; //displays average of odd numbers.
document.getElementById("averageEven").innerHTML = avgEven; //diplays average of even numbers.
document.getElementById("odd").innerHTML = oddarray.toString(); //displays all odd numbers that were entered.
document.getElementById("sumOddTotal").innerHTML = sumOdd.toString();
}
As you already have other answers with solutions to your particular issue, I would suggest a different approach. Think of the data you're manipulating: an array. Try to solve the issue only with data, no user input, no DOM manipulation; just data. This helps to separate concerns, and make your code easier to understand.
Since we're working with arrays, we can make use of some of the built-in JavaScript methods that are present in modern browsers, such as filter and reduce. These methods are in a way, alternatives to for loops, with some pre-defined behavior, and a callback function.
Now, let's think of the steps involved in solving your problem.
Get numbers from the user. We can represent this data as an array, as you were already doing.
We want all odd numbers, their sum and average.
We want all even numbers, their sum and average.
We display the data to the user.
In this solution I'm assuming you already have an array with the data, and will be focusing on points 2 and 3. Remember, think of data, user interaction shouldn't be mixed with your data logic. Instead of asking the user for a number on each loop, you could ask the user for a list of numbers directly; you avoid multiple prompts this way, and it lets you separate data and interaction nicely. Ideally you'd validate all user input to match your requirements.
// Helpers to work with numbers
var odd = function(x) {
return x % 2 === 0;
};
var even = function(x) {
return x % 2 !== 0;
};
var add = function(x, y) {
return x + y;
};
function solve(ns) {
// Solve the problem
// with odd or even numbers
var result = function(fn) {
var xs = ns.filter(fn); // odd or even
var sum = xs.reduce(add);
return {
numbers: xs,
sum: sum,
average: sum / xs.length
};
};
// Return an object
// with odd and even results
return {
odd: result(odd),
even: result(even)
};
}
var numbers = [1,2,3,4]; // from user input
var result = solve(numbers);
console.log(result.odd);
//^ {numbers: [2,4], sum: 6, average: 3}
console.log(result.even);
//^ {numbers: [1,2], sum: 4, average: 2}

can't convert undefined to object in javascript

Update: I have added the fiddle. Please refer here. use web console for error.
I am writing a code for traveling salesman problem. Here is the code :
var ind =[]; //values selected
var cp =[];
var X;
var Y;
var tour = [];
// no values selected in the starting
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
// distances at i,i infinity
for(i=0;i<friends_cnt;i++) {
distance[i][i] = 9999999999999;
}
var k = 0;
var X = 0;
tour[k] = X;
ind[X] = 1;
var i =1;
while(i<friends_cnt && ind[i] === 0) {
var min = 9999999999999;
// finding minimum of the undeleted values
for(j=0;j<friends_cnt;j++) {
if(ind[j] === 0) {
if(distance[X][j] < min) {
min = distance[X][j];
Y = j; // y is the min city
}
}
}
k = k+1; // counter for the starting city
tour[k] = Y; //city added
ind[Y] = 1;
X = Y;
i++;
}
k = k+1;
tour[k] = tour[1];
for(var q=0;q<k+1;q++) {
console.log(tour[q]);
}
});
});
now here whenever i run my program, it shows an error
TypeError: can't convert undefined to object
in the line
var min = 9999999999999;
My question is that is this because JavaScript cant handle large numbers or something else ?
Javascript's max number is 1.7976931348623157e+308 (aka the var Number.MAX_VALUE), so that shouldn't be an issue.
If you are trying to access an object of an object, it won't work.
You have distance[X][j]. That tries to access key j of distance[X]. To fix this, define distance[X] as an object:
distance[X] = [];
Other example:
var distance = [];
distance[i]
//undefined;
distance[i][i]
//syntax error
distance[i] = [];
distance[i][i]
//undefined;
For 2D arrays, see this question.
The problem is actually here:
distance[i][i] = 9999999999999;
If distance is undefined or an empty array, that statement will fail. This should fix it:
var distance = []; // <-- this is missing from the top of your code
// ...
if (!distance[i]) {
distance[i] = [];
}
distance[i][i] = 9999999999999;
Try this for minimum number
var min = int.MinValue
For max number
var max = int.MaxValue
Edited
Refer Reference
Number.Max_Value
Number.Min_Value
UPDATED
If you see your code you have filled the ind[] from 0
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
and in your while condition you have set value of i from 1. So for the last element it may be throwing error

How can I remove rows with unique values, keeping rows with duplicate values?

I have a spreadsheet of surveys, in which I need to see how particular users have varied over time. As such, I need to disregard all rows with unique values in a particular column. The data looks like this:
Response Date Response_ID Account_ID Q.1
10/20/2011 12:03:43 PM 23655956 1168161 8
10/20/2011 03:52:57 PM 23660161 1168152 0
10/21/2011 10:55:54 AM 23672903 1166121 7
10/23/2011 04:28:16 PM 23694471 1144756 9
10/25/2011 06:30:52 AM 23732674 1167449 7
10/25/2011 07:52:28 AM 23734597 1087618 5
I've found a way to do so in Excel VBA:
Sub Del_Unique()
Application.ScreenUpdating = False
Columns("B:B").Insert Shift:=xlToRight
Columns("A:A").Copy Destination:=Columns("B:B")
i = Application.CountIf(Range("A:A"), "<>") + 50
If i > 65536 Then i = 65536
Do
If Application.CountIf(Range("B:B"), Range("A" & i)) = 1 Then
Rows(i).Delete
End If
i = i - 1
Loop Until i = 0
Columns("B:B").Delete
Application.ScreenUpdating = True
End Sub
I'd like to do it in Google Spreadsheets with a script that won't have to be changed. Closest I can get is retrieving all duplicate user ids from the range, but can't associate that with the row. That code follows:
function findDuplicatesInSelection() {
var activeRange = SpreadsheetApp.getActiveRange();
var values = activeRange.getValues();
// values that appear at least once
var once = {};
// values that appear at least twice
var twice = {};
// values that appear at least twice, stored in a pretty fashion!
var final = [];
for (var i = 0; i < values.length; i++) {
var inner = values[i];
for (var j = 0; j < inner.length; j++) {
var cell = inner[j];
if (cell == "") continue;
if (once.hasOwnProperty(cell)) {
if (!twice.hasOwnProperty(cell)) {
final.push(cell);
}
twice[cell] = 1;
} else {
once[cell] = 1;
}
}
}
if (final.length == 0) {
Browser.msgBox("No duplicates found");
} else {
Browser.msgBox("Duplicates are: " + final);
}
}
This is maybe not very efficient, but I think it's what you want:
var ar=[1,3,3,5,6,8,6,6];
console.log("Before:");
display(ar);//1 3 3 5 6 8 6 6
var index=[];
var ar2=[];
for(var a=0;a<ar.length;a++)
{
var duplicate=false;
for(var b=0;b<ar.length;b++)
{
if(ar[a]==ar[b]&&a!=b)
{
duplicate=true;
}
}
if(!duplicate)
{
index.push(a);
}
}
for(var a=0;a<index.length;a++)
{
ar[index[a]]=null;
}
for(var a=0;a<ar.length;a++)
{
if(ar[a]!=null)ar2.push(ar[a]);
}
console.log("After:");
display(ar2);//3 3 6 6 6
function display(x)
{
for(var a=0;a<x.length;a++)console.log(x[a]);
}
The fiddle : http://jsfiddle.net/mageek/6AGQ4/
And a shorter version that is as a function :
var ar=[1,3,3,5,6,8,6,6];
function removeUnique(x)
{
var index=[];
var ar2=[];
for(var a=0;a<ar.length;a++)
{
var duplicate=0;
for(var b=0;b<ar.length;b++)if(ar[a]==ar[b]&&a!=b)duplicate=1;
if(!duplicate)index.push(a);
}
for(var a=0;a<index.length;a++)ar[index[a]]=null;
for(var a=0;a<ar.length;a++)if(ar[a]!=null)ar2.push(ar[a]);
return x;
}
ar=removeUnique(ar);
The fiddle : http://jsfiddle.net/mageek/6AGQ4/2
I'd suggest going for something simple.
Create a short script that flags duplicates
Write the formula directly into the cell "=flagDuplicate(C2,C$2:C$10)"
Copy the forumla down the column
Use Spreadsheet's built in QUERY formula to pull the information you need
"=QUERY(A1:E10; "SELECT * WHERE E = TRUE"; 1)"
Here is a simple function to flag duplicates
function flagDuplicate(value, array) {
var duplicateCounter = 0;
for (var i=0; i<array.length; i++){
if (array[i] == value){ // I avoid === in Spreadsheet functions
duplicateCounter++;
}
}
if (duplicateCounter > 1){
return true;
}else{
return false;
}
}
Too many functions on a large table can slow things down. If it becomes a problem, you can always copy and "paste values only" - that will retain the information but remove the functions.
Best of luck.
Note: When I tested this I noticed that can take a while before the spreadsheet recognizes the new custom function (gives error like can't find function FLAGDUPLICATE)
You could also do it using arrays to handle the whole sheet at once :
function removeUnique(){
var col = 2 ; // choose the column you want to check for unique elements
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getDataRange().getValues();// get all data
data.sort(function(x,y){
// var xp = Number(x[col]);// use these to sort on numeric values
// var yp = Number(y[col]);
var xp = x[col];// use these for non-numeric values
var yp = y[col];
Logger.log(xp+' '+yp); // just to check the sort is OK
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on column col numeric ascending
});
var cc=0;
var newdata = new Array();
for(nn=0;nn<data.length-1;++nn){
if(data[nn+1][col]==data[nn][col]||cc>0){
newdata.push(data[nn]);
++cc;
if(cc>1){cc=0}}
}
ss.getDataRange().clearContent(); // clear the sheet
sh.getRange(1,1,newdata.length,newdata[0].length).setValues(newdata);// paste new values sorted and without unique elements
}
EDIT : here is the version that keeps all duplicates (the working one)
function removeUnique(){
var col = 2 ; // choose the column you want to check for unique elements
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getDataRange().getValues();// get all data
data.sort(function(x,y){
// var xp = Number(x[col]);// use these to sort on numeric values
// var yp = Number(y[col]);
var xp = x[col];// use these for non-numeric values
var yp = y[col];
Logger.log(xp+' '+yp); // just to check the sort is OK
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on column col numeric ascending
});
var newdata = new Array();
for(nn=0;nn<data.length-1;++nn){
if(data[nn+1][col]==data[nn][col]){
newdata.push(data[nn]);
}
}
if(data[nn-1][col]==data[nn][col]){newdata.push(data[nn])}
ss.getDataRange().clearContent(); // clear the sheet
sh.getRange(1,1,newdata.length,newdata[0].length).setValues(newdata);// paste new values sorted and without unique elements
}

Categories

Resources