Loop through array and adding sums of each section - javascript

So I have 11 checkboxes that are split up into 4 different categories. Each category has 3 check-boxes to choose from except for the last, which has 2. I want to check if a check-box within each category is checked and find out how many of them are checked within that category. I might be over thinking this one but so far I have this as my JS:
//I initially receive the checkbox values as a string that has 1 for checked and 0 for not checked.
var split_string = checkbox_string.split(",").map(Number);
console.log(split_string);
var sec = [];
var total = 0;
var split_int=[];
var sliced = 0;
for (var i = 0; i <= 3 ; ++i) {
sec[i] = split_string.splice(0,3);
console.log(sec[i]);
for(var j = 0; j < sec[i].length; ++j){
sliced = sec[i][j];
total += sliced;
}
console.log("total= "+ total);
window['section' + i] = total;
}
So as of right now I'm pretty close, although I'm sure there is a simpler way of doing this. I split the string into 4 arrays (ex.[1,0,1] [0,0,1] [1,1,1] [1,0]). Then I take each individual number from each array and add it to the total.
As of right now it will return the 1st three added, then it returns the 2nd three added to the first three on its 2nd loop. So for example total=2 the first time around then total=3 the 2nd time around, but I want total the 2nd time around to be only based on the 2nd array (so it would be 1 if following the ex. above).

function summer(p,c,i) {
if( i%3==0 ) p.push(0);
p[p.length-1] += c;
return p;
}
var split_string = [1,0,1,0,0,1,1,1,1,1,0];
split_string.reduce(summer,[]); // [2, 1, 3, 1]

Well I'm dumb, all I needed to add was total = 0 at the bottom of the array. But I'd still be interested if there is better/more simple ways of doing this.

Related

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.

Include duplicates in for and if loop of array as count number is too small

I'm new to javascript so any help would be greatly appreciated.
What I'm trying to do is cycle through every element in the array and count the number of times the value of an element matches a given condition (even if the value is duplicated).
function loaddata(xml) {
var count = 0;
var i;
var xmlDoc = xml.responseXML;
var z = xmlDoc.getElementsByTagName("group");
if (value1 <= value2) {
for (i = 0; i < (0 + z.length); i++) {
if (z[i].getElementsByTagName("name")[0].childNodes[0].nodeValue == "John") {
count++;
}
}
}
$('#count1').html(count);
};
The count value outputted is too small. I believe the reason for this that the for loop isn't iterating through all elements in the array. When I remove the second if loop and output the count for just the for loop this value is also too small. I believe that the for loop isn't searching through the duplicate elements of the array (i.e. it is ignoring them so that they aren't then fed into the second if loop). Is it possible to specify that the for loop include duplicates?
Do a console.log(z[i].getElementsByTagName("name")) and open your browser's console, and see if that array has data in it.
Then console.log(z[i].getElementsByTagName("name")[0].childNodes) and make sure you have nodes in it.
Also, do you have many <group></group> tags? Because that's what you are selecting with var z = xmlDoc.getElementsByTagName("group");
I hope that helps,

JavaScript - Looping array less than I should

I'm trying to loop an array which contains a list of elements returned by ClassName, but I can't loop all of them, because of the next situation:
var list = document.getElementsByClassName('class');
for (var i = 0; i < list.length; i++) {
var theClass = list[i].className; //once got list[i].
theClass = theClass.replace('class', '');
list[i].className = theClass; //twice got list[i].
}
If the size of the list is = 4, I just can loop two times, because I'm getting twice each position per loop. Do you know what I can do and why it happens? Thank you.
The data structure returned by getElementsByClassName is Array-like and dynamic based on the DOM. Once you replace the class on the list item in question, you end up losing an item per iteration.
To fix this, you can take a copy of the returned values first before operating on them, or work backwards.
Take a copy:
var list = document.getElementByClassName('class')
var realList = []
Array.prototype.push.apply(realList, list)
for (var i = 0; i < realList.length; i++) {
// do changes as you have already
}
Working backwards:
var list = document.getElementsByClassName('class')
for (i=list.length - 1; i >= 0; i--) {
// do changes to list[i]
}
Another poster briefly mentioned a while loop which also works, but then their answer disappeared (I don't want to take credit for this!):
var list = document.getElementsByClassName('class')
while (list.length != 0) {
// do changes to list[0]
}
If you write out what happens in your initial code, you can see the problem more clearly:
Iteration 1: i=0, list=[a,b,c,d], length = 4, list[i]=a
Iteration 2: i=1, list=[b,c,d], length = 3, list[i]=c
Before Iteration 3: list=[b,d], i=2, length = 2, loop breaks
Now writing out what happens when using the reverse loop:
Iteration 1: i=3, list=[a,b,c,d], length = 4, list[i]=d
Iteration 2: i=2, list=[a,b,c], length = 3, list[i]=c
Iteration 3: i=1, list=[a,b], length = 2, list[i]=b
Iteration 4: i=0, list=[a], length = 1, list[i]=a
All these solutions are variations on this solution of avoiding using i to reference the middle parts of the array-like result value of getElementsByClassName so that the dynamic nature of it is dealt with.

Result of FOR-loop if there is no related item

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

dice random value 1 to 10 and overthrow in Javascript

Hi I have code like this:
$('#Generator_Rzutow').click (function(){
var val1 = $('#rzucane').val();
var val2 = $('#zachowywane').val();
var zbior = [];
var limit = 10;
alert (val1);
alert (val2);
for (var i=0; i<val1;i++){
var wynik_rzutu = 1+Math.floor(Math.random()*10);
if (wynik_rzutu<limit){
zbior.push(wynik_rzutu);
} else {
limit = limit+10;
wynik_rzutu = wynik_rzutu+1+Math.floor(Math.random()*10);
if (wynik_rzutu<limit){
zbior.push(wynik_rzutu);
} else {
limit = limit+10;
wynik_rzutu = wynik_rzutu+1+Math.floor(Math.random()*10);
zbior.push(wynik_rzutu);
}
}
}
$('#wypisz').text (zbior);
});
My problem is that when it randoms '10' it sometimes add 10 to array, when it should randomize another time and ad it to prev value.
My second question is. How to get it to randomize another value and ad it to prev as long as it randomize 10. For ex: so it could get numer 74, when it randomize 7x10 and 4, and then it past it to array.
I know I should do it by while lop but I couldn`t get working solition, so instead I put 'if'
The first problem is that you don't reset your limit at each iteration. You start with limit 10, then when the first number larger than 10 is generated, the limit is increased to 20 and all subsequent numbers will be compared to 20 to see if they are added to the array or re-generated (and they will all be added to the array, since they are all smaller than 20).
As for your second problem, i think this piece of code behaves accordingly:
for (var i=0; i<val1;i++){
var wynik_rzutu = 0, limit = 0;
while (wynik_rzutu >= limit) {
wynik_rzutu += 1+Math.floor(Math.random()*10);
limit += 10;
}
zbior.push(wynik_rzutu);
}
You can also add a counter to prevent it from an infinite cycle (if Math.random() always returns 0.9 for example), but i doubt it is something you really require.

Categories

Resources