Result of FOR-loop if there is no related item - javascript

in a Podio calculation_field A I sum up the numbers of each related item (from another app) which contain "searchstring_1" in a text_field, in calculation_field B all related items which contain "searchstring_2"
No problem with the following code - IF there exists a related item. But if there exists no related item the "1" (= "nothing found"?) is displayed as "result". I tried several things, but can't find a solution for a calculation like: IF there is no related item then result = 0 (or "" or null), else let run the for-loop. Has anybody a tip what I can do?
Thanks,
Rainer
var str = all of text_field;
var num = all of number_fields;
var total = 0;
for(var i = 0; i < num.length ; i++) {
if (str[i].indexOf("searchstring_1") === 0) {
total += num[i];
}
}

The calculation field always returns the last used value if you don't explicitly specify the return value. Maybe in your case the last value of i, str[i].indexOf("searchstring_1") would return -1, I think...
To make sure that the value of totalis returned, simply add
total;
at the end of your calculation field value.
Enjoy,
Michael / Hamburg

Related

Apps Script For Loop stuck at 0 in iteration although it is running

I have an array 'vnData' containing 5, 6 rows from where I am trying to extract 3rd column values (based on a criteria) and insert to a new array. Here is my code
for (odr = 0; odr < vnData.length; odr++){
Logger.log(vnData);
tempOdr = vnData[odr][3];
Logger.log(odr);
Logger.log(tempOdr);
Logger.log(vnData[odr][3]);
for(k = 0; k < vnData.length; k++){
if(vnData[k][3] = tempOdr){
odrVal = odrVal + vnData[k][11];
}
}
if(odrVal > 0){
affOdrSet.push(tempOdr);
}
Logger.log(affOdrSet);
}
Logger gives right value of odr in Logger.log(odr); but in Logger.log(vnData[odr][3]); I am always getting a result where value of odr is 0.
So for each iteration I get value from first row. Please help what is wrong in it.
One more thing, if I log Logger.log(vnData[3][3]) in place of Logger.log(vnData[odr][3]) then for first iteration it gives me right value from row 4 but for all subsequent iterations even Logger.log(vnData[3][3]) gives value from first row which is really weird.
The problem is the expression of the first if statement. Instead of
vnData[k][3] = tempOdr
use
vnData[k][3] === tempOdr
The above because = is the assign operator but it's very likely that instead of assigning tempOdr to vnData[k][3] what you want to compare them.

Jquery check if is last negative number in an object array

I need to check if in an object array the current value is the last negative.
For example:
var myArray = [
name:'a' value:'5','-1','-5','7','-3'
name:'b' value:'7','-5','-4','7','5'
]
In a for loop, if current value is negative, i need check if is the last negative value in the array for this name.
For example In name 'b':
current value = -5, it's negative, so, Is the last negative? No
current value = -4, it is negative, so, Is the last negative? Yes
Start code for the example:
lastName = '';
for(i = 0; i < myArray.length; i++){
if(myArray[i].value < 0 && lastName == myArray[i].name){
// then it's negative, now check if is the last negative value
}
lastName = myArray[i].name;
}
Inside the if I dont understand how to do this, can someone help me?
Not entirely sure what you're trying to achieve as the question is hard to understand and your example code is...well I dunno what it is but it ain't valid JS.
Anyhow,
If you're looking to find out if the last value of the values array per object is negative. Do the below
for(var i = 0; i < myArray.length; i++) {
var currObj = myArray[i];
var lastValue = currObj.value[currObj.value.length - 1];
var valIsNegative = parseInt(lastValue) < 0;
if (valIsNegative) {
// Last value is negative, do things.
}
if (!valIsNegative) {
// Last Value is positive, do things.
}
}
Again, not sure if this is even relevant to your question as it is hard to decipher. Let me know and I'll delete if it's not.

How to sort elements of array in natural order with mixed (letters and numbers) elements

i am trying to create google-form which is used to register students agreements on practice. Every agreement is registered and got agreement number which format is Last to digits of current year-T-number of agreement at this year/M. For example for now it is 17-T-11/M. The number of agreement currently is written by person which is responsible for practice.
Here is code of script below:
function onChange(e)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var range = sheet.getDataRange();
var values = range.getValues();
var comboValues = ['16-T-105/M'];
// removing titles from 0 column and 1 line (titles)
for (var i = 1; i <= values.length; i++) {
var v = values[i] && values[i][0];
v && comboValues.push(v)
}
// Sort the values
comboValues.sort(
function(a, b) {
if (b.toLowerCase() < a.toLowerCase()) return -1;
if (b.toLowerCase() > a.toLowerCase()) return 1;
return 0;
}
);
Logger.log(comboValues);
// google-form modification
var form = FormApp.openById('1SHgVIosoE34m9cny9EQySljvgnRpzffdFEZe-kzNOzA');
var items = form.getItems();
for (i = 4; i < items.length; i++) {
Logger.log("ID: " + items[i].getId(), ': ' + items[i].getType());
}
form.getItemById('2087613006').asListItem().setChoiceValues(comboValues);
I got issue which is related with lexicographical order. Person which register agreement choose from list last registered agreement number: i tryed to do that last registered agreement number will always be at list top. As time when i started this everything was fine (it started with number 16-T-105/M), but new year come and soon after 17-T-10/M agreement was registered i got issue, that 17-T-10/M was not on list top. Soon i realised that this happens because script use lexicographical order and "thinks" that 2 is more than 10. So i understood that i somehow will have to change that order and do that 2 is less than 10, 11 is less than 101 and so on.
My question is how to do that? I guess that i need to sort array elements in natural order - but i do not have idea how to do this.
I tryed to google how to do it , but result was not satisfactory - maybe my knowledge of coding is pretty limited (i am PhD student of Psychology, not Informatics) :)
Maybe someone will help how to solve that problem.
Updates:
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1FH5qYTrLUNI2SCrcaqlwgu8lzAylaTkZsiALg0zIpCM/edit#gid=1620956794
Link to google-form (Copy of actual form): https://docs.google.com/forms/d/e/1FAIpQLSerJfkv1dgHexUwxppXNyhb46twOZgvEMOIVXSOJoED3SLmyQ/viewform
You should adjust the sorting method to account of the peculiarities of the data. Here is one way to do this: the function splitConvert processes each string, splitting it by non-word characters and then converting what can be converted to integers (and lowercasing the rest). Then the comparison goes through this array one by one.
comboValues.sort(
function(a, b) {
var as = splitConvert(a);
var bs = splitConvert(b);
for (var i = 0; i < as.length; i++) {
if (bs[i] < as[i]) return -1;
if (bs[i] > as[i]) return 1;
}
return 0;
}
);
function splitConvert(str) {
return str.split(/\W/).map(function(part) {
var x = parseInt(part, 10);
return isNaN(x) ? part.toLowerCase() : x;
});
}
This is not the most performance-oriented solution: the split-parse function will be repeatedly called on the same strings as they are being sorted. If this becomes an issue (I don't really think so), one can optimize by having one run of conversion, creating an array of arrays, and then sorting that.

Checking for time conflicts, want to show just 1 warning

I have a form where the user can add X number of rows, with each row having a start time and end time input.
The rows can be added as the user likes, and the times do not have to be entered sequentially, but must not conflict when submitting the form.
So far, I am able to check for conflicts, using a couple of for loops and checking each start and end time against the rest.
The problem I am facing, is that obviously, if row 1 and 2 conflict, my code is logging two conflicts (logically correct!)
I only want to show the first conflict, as once this is resolved, naturally, the second conflict is.
My code for far:
$('form').submit(function(event){
event.preventDefault();
var errors = [];
var data = serializedToObject($(this).serializeArray());
for(var i = data.row.length; i--;) {
for(var s = data.start.length; s--;) {
if(s != i) {
if(data.start[i] < data.end[s] && data.start[s] < data.end[i]) {
errors.push('Conflict between ' + data.row[i] + ' and ' + data.row[s]);
}
}
}
}
if(errors.length === 0) {
this.submit();
} else {
console.log(errors);
}
});
(serializedToObject simply converts the form data to an object)
So how do I have my code only push 1 of the conflicts to the array?
I tried adding the row ID to an object and pushing that to the array, but it wouldn't log additional conflicts later down the line e.g. Row 1 conflicts with 2 and 4, the conflicts between 1 and 4 would not be mentioned, as row 1 is already in the array.
I have an answer for you, but it is not that efficient (again O(n^2), as you code in the question ).
If i understood correctly , data.start.length and data.row.length has to be equal, right? If so, if you count the s from i-1 to 0, and the errors are (1,2) and (2,1) , (1,2) won't get cought becouse the second loop starts from i-1, in the case where i=1, s starts directly from 0. just take a look at the code below (only included the for loops) :
var length = data.row.length;
for( var i = length; i>0; i-- ) {
for( var s = i-1; s>0; s-- ) {
if(data.start[i] < data.end[s] && data.start[s] < data.end[i]) {
errors.push('Conflict between ' + data.row[i] + ' and ' + data.row[s]);
}
}
}
I hope somebody will come with a comment with an idea to optimise this, maybe O(n) if it is possible :D. But this will work for you , and in case where you don't have length variable as big as 100.000, it will work just swell!

Trying to search through array of strings for a pattern the user inputs - javascript

var p = ["array of words", "i really hate the sun", "i'm TIred"]
function findword(contents,pattern){
var answer;
var idx;
var counter = 0;
var pat_lc = pattern.toLowerCase();
for (var i = 0; i <= contents.length-1; i++){
var str_lc = contents[i].toLowerCase();
idx = str_lc.indexOf(pat_lc)
if (idx >= 0){
answer = i
}
else{
answer = "-1"
}
}
alert(answer)
}
findword(p,"words")
I'm trying to find the index of the array for a certain word, in an array of strings, however it only works for certain words in the array above. For example, on the last line of the code, when I chose to search for "words" it returns the value of "answer" and "idx" -1 when it should be 0 and 9 respectively. However, when I search for "tired", the value of "answer" is 2 and "idx" is 4 (which is correct). Why do some words work and others return the value of -1?
Here's a modified working version that will find all matches
var p = ["array of words", "i really hate the sun", "i'm TIred"]
function findword(contents,pattern){
var matches=[];
var idx;
var pat_lc = pattern.toLowerCase();
for (var i = 0; i <= contents.length-1; i++){
var str_lc = contents[i].toLowerCase();
idx = str_lc.indexOf(pat_lc)
if (idx >= 0){
matches.push({ idx: i, position: idx})
}
}
return matches
}
Several problems
answer and idx get overwritten ever pass of the for loop. So regardless if a match was found...only last pass is returned. I saved the results into separate array that gets returned. Code you provided didn't do anything with idx.
Can test output for length to see if matches exist...no matches will return empty array with no length
Come to think of it...not sure what output you want
DEMO
You should stop as soon as you find a solution.
Your program only stops when it iterated over the whole array. But what if the answer what not in the last element ? Then answer will contain -1.
You can init answer at -1 and continue your for loop as long as i is less than content.length and answer is equal to -1 : http://jsfiddle.net/#&togetherjs=dbVcN8JkKP

Categories

Resources