jQuery for loop every third - javascript

Why is it only every third when I change i = 0 to i = 1 but then I don't get all results.
$.getJSON('search.php', {q: query, ajax: 'true'}, function(j){
var options = '';
for (var i = 0; i < j.length; i++) {
if(i % 3 == 0) {
// every third
} else {
}
$("#profile-search-results").html(options);
}
});

I think what are trying to do is to get elements at indexes 3, 6, 9... etc but your condition is executed for first, fifth, eighth... etc elements.
The problem is your loop is starting with 0, so 0%3 will return 0... since the element index in jQuery starts with 0, what you need is elements at indexes 2, 5, 8,... etc. So you should check for reminder 3 == 2
for (var i = 0; i < j.length; i++) {
if (i % 3 == 2) {
// every third
} else {
}

% is modulo operator.
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
7 % 3 = 1
...
So what you have is normal.

Related

Refining code: Is there a better way to map one (shorter) array to another (longer) array of objects in Javascript?

I have a React project that uses an array of colors for styling a few things:
export const backlightArray = [
theme.capri,
theme.aqua,
theme.oceanGreen,
theme.yellow,
'orange',
theme.lightRed
];
and another array of objects with attributes for anchor tags:
const siteStart = [
{ label: 'StackOverflow', href: 'https://stackoverflow.com' },
{ label: 'rwieruch', href: 'https://www.robinwieruch.de/blog' },
{ label: 'ITNext.io', href: 'https://itnext.io/' },
{ label: 'Dev.to', href: 'https://dev.to/' },
{
label: `ycombninator ('Hacker News')`,
href: 'https://news.ycombinator.com/'
},
{ label: 'OpenBase.io', href: 'https://openbase.io/' },
{ label: 'Coolors.co', href: 'https://coolors.co/' },
{ label: 'GitHub', href: 'https://www.github.com/' },
{ label: '/r/homelab/', href: 'https://www.reddit.com/r/homelab/' },
];
(I've shortened this for the example, but right now this array has 14 links).
The colors array is shorter than the array of site objects. I want the colors to repeat once they colors array ends, so I came up with this loop to add colors from the backlightArray for the length of the siteStart array:
let siteListColorsArray = [];
for (let i = 0; i < siteStart.length; i++) {
if (siteListColorsArray.length < siteStart.length) {
backlightArray.map(color => siteListColorsArray.push(color));
}
}
and then map those colors along with other shared attributes for the links like so:
const sites = siteStart.map((site, idx) => {
site.target = '_blank';
site.rel = 'noopener noreferrer';
site.id = `${site.label.slice(0, 3)}-${idx}`; // this is for 'key'
site.color = siteListColorsArray[idx];
return site;
});
export default sites;
I wrote it this way so I could add /remove label and href objects to/from the siteStart array and not have to mess with any other attributes in the finished objects.
It works properly, but I am just wondering: does this code look decent to other people? If you were to do something similar, what would you do differently?
I think this should do the job for you:
colorsLastIndex = backlightArray.length - 1;
const sites = siteStart.map((site, idx) => {
const newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1 : idx;
site.id = `${site.label.slice(0, 3)}-${idx}`; // this is for 'key'
site.color = backlightArray[newIndex];
return site;
});
I got a great answer that replaced this nested loop to create a longer array of colors:
let siteListColorsArray = [];
for (let i = 0; i < siteStart.length; i++) {
if (siteListColorsArray.length < siteStart.length) {
/* lengths: (0) (13) */
backlightArray.map(color => siteListColorsArray.push(color));
/* (length = 6) (iterates until > 13) */
}
}
with this ternary expression to subtract 1 from the modulus of index % backlightArray.length once the index is greater than 5 (backlightArray.length -1):
let colorsLastIndex = backlightArray.length - 1;
const sites = siteStart.map((site, idx) => {
site.id = `${site.label.slice(0, 3)}-${idx}`;
const newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1 : idx;
site.color = backlightArray[newIndex];
return site;
});
however, this solution made the newIndex return -1, resulting in a missing color value for that iteration. When I console.log(newIndex), you can see that the number goes below 0 and does not return to 5 - I wrote out the steps to illustrate (I performed the calculations in the console to verify):
/* start first iteration w/ index */
0
1
2
3
4
5
/* start newIndex = idx > colorsLastIndex ? (idx % colorsLastIndex) - 1
(6) (6) (6) (5) (- 1) */
0 // 6 % 5 - 1
1 // 7 % 5 - 1
2 // 8 % 5 - 1
3 // 9 % 5 - 1
-1 // 10 % 5 - 1
0 // 11 % 5 - 1
1 // 12 % 5 - 1
2 // 13 % 5 - 1
Here's the solution that worked for me (note: backlightArray.length = 6):
const newIndex = idx >= backlightArray.length ? idx % backlightArray.length : idx;
site.color = backlightArray[newIndex];
console.log(newIndex):
/* start first iteration w/ idx */
0
1
2
3
4
5
/* start newIndex = (idx) >= backlightArray.length ? idx % backlightArray.length
(6) (6) (6) % (6) */
0 // 6 % 6
1 // 7 % 6
2 // 8 % 6
3 // 9 % 6
4 // 10 % 6
5 // 11 % 6
0 // 12 % 6
1 // 13 % 6
Once the index gets to 6, which is 1 above 5 (the last color in backlightArray), 6 = backlightArray.length, and the condition becomes true. Then, the remainder of index divided by 6 equals 0, and increases by one thereafter until the index reaches another factor of 6 (e.g. 12), at which point it becomes 0 again. This condition also works:
newIndex = idx + 1 > backlightArray.length ? idx % backlightArray.length : idx;
idx + 1 might be a little more illustrative of the logic.
This is a great pattern that reduces the need for unwieldy-looking nested loops. Thanks so much for sharing!

is (i % 3 == 0) means ( i % 3 == false )?

I am a beginner learning JS. Can anyone explain to me why "1" on the output?
here it is:
for (var i = 1; i <= 15; i++) {
if (i % 2 == 0) {
i += 2;
} else if (i % 3 == 0) {
i++;
}
console.log(i);
}
output : 1, 4, 5, 8, 10, 11, 14, 16
I can figure out why the output equal to 4, 5, 8, 10, 11, 14, 16 , however, I don't understand why 1 is there as output...
When the value of i is 1, both conditional statement you defined doesn't get executed.
for (var i = 1; i <= 15; i++) {
if (i % 2 == 0) {
console.log( 'inside if' );
i += 2;
} else if (i % 3 == 0) {
console.log( 'inside else-if' );
i++;
} else {
console.log( 'neither if nor else-if' );
}
console.log(i);
}
Remainder is always 1 when you divide it with 2 or 3, which is not equals to 0.
console.log( 1 % 2 );
console.log( 1 % 3 );
When you look at your code the console is out of if-else condition, means that it is printing i from condition and out of condition, Your for-loop start from 1, when i=1, condition skipped and console executed and print i which is equal to one
I think that's why
And
I % 3 == 0 means I % 3 == false
because
var i = 2;
if (i % 2 == 0)
{
console.log(0)
}
if (i % 2 == false)
{
console.log(0)
}
all the answer is 0

find sum of multiples 3 and 5, JS

I'm given a number and I need to find the sum of the multiples of 3 and 5 below the number.
For example:
20 => 78 = 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18
My code works, but not for numbers greater than 1,000,000 (I tested it for 100,000 - it gives the result with 2sec delay). So, it should be optimized. Could someone help me? Why is my code slow? Thanks.
My logic is as follows:
add multiples to an array
filter duplicate values
sum all values
my code:
function sumOfMultiples(number) {
let numberBelow = number - 1;
let numberOfThrees = Math.floor(numberBelow / 3);
let numberOfFives = Math.floor(numberBelow / 5);
let multiples = [];
let multipleOfThree = 0;
let multipleOfFive = 0;
for (var i = 0; i < numberOfThrees; i++) {
multiples.push(multipleOfThree += 3);
}
for (var j = 0; j < numberOfFives; j++) {
multiples.push(multipleOfFive += 5);
}
return multiples
.filter((item, index) => multiples.indexOf(item) === index)
.reduce((a, b) => a + b);
}
You can also do this without using any loops.
For example if N is 1000, the sum of all multiples of 3 under 1000 is 3 + 6 + 9 ..... 999 => 3( 1 + 2 + 3 .... 333)
Similarly for 5, sum is 5(1 + 2 + 3 .... 200). But we have to subtract common multiples like 15, 30, 45 (multiples of 15)
And sum of first N natural numbers is N*(N+1)/2;
Putting all of this together
// Returns sum of first N natural numbers
const sumN = N => N*(N+1)/2;
// Returns number of multiples of a below N
const noOfMulitples = (N, a) => Math.floor((N-1)/a);
function sumOfMulitples(N) {
const n3 = noOfMulitples(N, 3); // Number of multiples of 3 under N
const n5 = noOfMulitples(N, 5); // Number of multiples of 5 under N
const n15 = noOfMulitples(N, 15); // Number of multiples of 3 & 5 under N
return 3*sumN(n3) + 5*sumN(n5) - 15*sumN(n15);
}
You can just run a loop from 1 to number, and use the modulo operator % to check if i divides 3 or 5:
function sumOfMultiples(number) {
var result = 0;
for (var i = 0; i < number; i++) {
if (i % 5 == 0 || i % 3 == 0) {
result += i;
}
}
return result;
}
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
You can do that just using a single loop.
function sumOfMultiples(number) {
let sum = 0;
for(let i = 1; i < number; i++){
if(i % 3 === 0 || i % 5 === 0){
sum += i;
}
}
return sum;
}
console.time('t');
console.log(sumOfMultiples(100000))
console.timeEnd('t')
You can do something like this
Set the difference equal to 5 - 3
Start loop with current as 0, keep looping until current is less than number,
Add 3 to current in every iteration,
Add difference to current and check if it is divisible by 5 only and less than number, than add it final result,
Add current to final result
function sumOfMultiples(number) {
let num = 0;
let difference = 5 - 3
let current = 0
while(current < number){
current += 3
let temp = current + difference
if((temp % 5 === 0) && (temp %3 !== 0) && temp < number ){
num += temp
}
difference += 2
if(current < number){
num += current
}
}
return num
}
console.log(sumOfMultiples(20))
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
you can do something like this
function multiplesOfFiveAndThree(){
let sum = 0;
for(let i = 1; i < 1000; i++) {
if (i % 3 === 0 || i % 5 === 0) sum += i;
}
return sum;
}
console.log(multiplesOfFiveAndThree());

Getting a array.push to do nothing

Trying to figure out a way that if the results of my loop equals undefined, to have my array.push do nothing. this is my code.
barcodes.sort();
var first = barcodes.slice(0, (barcodes.length + 1) / 2);
var second = barcodes.slice(((barcodes.length + 1) / 2), barcodes.length);
var result = [];
for (var i = 0; i < barcodes.length; i++) {
if (i % 2 === 0) {
result.push(first[i / 2]);
result.push(second[parseInt(i)/2]);
}else {
}
}
getting results when its odd as such: (when even is fine)
array results (12) ["1001", "9003", "3001", "9005", "3002", "9006", "3003", "9007", "9001", "9008", "9002", undefined]
result.push(second[parseInt(i)/2]);
This is undefined if you have an odd number because second.length is one less than half of barcodes. So if barcodes.length == 11, that second push is pushing second[5] when second.length == 5. This doesn't exist since indices start at 0
barcodes = ["1001", "9003", "3001", "9005", "3002", "9006", "3003", "9007", "9001", "9008", "9002"];
barcodes.sort();
var first = barcodes.slice(0, (barcodes.length + 1) / 2);
var second = barcodes.slice(((barcodes.length + 1) / 2), barcodes.length);
var result = [];
for (var i = 0; i < barcodes.length; i++) {
if (i % 2 === 0) {
result.push(first[i / 2]);
if(second[(i / 2)]) {
result.push(second[(i / 2)]);
}
}
}
console.log(result);
You could add this line: if(second[(i / 2)]) to avoid the undefined but again I'm not 100% sure what your end goal is so I'm not sure if this fully answers the question
You could take the barcode array and take an ofset for the second value for pushing.
The adjustment for the length keeps same element groups and add only at the end an undefined.
Examples:
given
barcode 0 1 2 3 4 5 6 7 8
first 0 1 2 3 4
second 5 6 7 8
result
0 5 1 6 2 7 3 8 4 undefined
given
barcode 0 1 2 3 4 5 6 7 8 9
first 0 1 2 3 4
second 5 6 7 8 9
result
0 5 1 6 2 7 3 8 4 9
var barcodes = [0, 1, 2, 3, 4, 5, 6, 7, 8],
result = [],
i,
l = (barcodes.length + 1) >> 1;
for (var i = 0; i < l; i++) {
result.push(barcodes[i], barcodes[i + l]);
}
console.log(result);

Combination Algorithm without sort()

I need results starting from the beginning with 123 as shown below. I want to print from the beginning without sort().
1 2 3
1 2 4
1 2 5
.....
3 5 6
4 5 6
But, The results are shown below.
4 5 6
3 5 6
2 5 6
1 5 6
3 4 6
2 4 6
1 4 6
2 3 6
1 3 6
1 2 6
3 4 5
2 4 5
1 4 5
2 3 5
1 3 5
1 2 5
2 3 4
1 3 4
1 2 4
1 2 3
result = "";
var N = 6;
var M = 3;
var arr = new Array(M);
combi(N, M, arr, M);
alert(result);
function combi(n, r, arr, sz) {
var i = n + 1;
while (i-- > r) {
// choose the first element
arr[r - 1] = i;
if (r > 1) { // if still needs to choose
// recursive into smaller problem
combi(i - 1, r - 1, arr, sz);
} else {
// print out one solution
var j = -1;
while (++j < sz) {
result += arr[j] + " ";
}
result += "\n";
}
}
}
Beside the inverting of all, you could start with one and iterat until the wanted value.
function combination(n, r) {
function iter(i, temp) {
if (temp.length === r) { // set complete
result.push(temp.join(' ')); // join values
return;
}
if (i + r > n + 1 + temp.length) { // exit early
return;
}
iter(i + 1, temp.concat(i)); // take the value
iter(i + 1, temp); // go without the value
}
var result = []; // result set
iter(1, []); // start with 1 and
return result; // empty array for collecting sets
}
console.log(combination(6, 3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can revert the order by changing your code this way:
function combi(n, r, arr, sz) {
var i = r - 1;
while (i++ < n) {
// choose the first element
arr[r - 1] = i;
if (r > 1) { // if still needs to choose
// recursive into smaller problem
combi(i - 1, r - 1, arr, sz);
} else {
// print out one solution
var j = -1;
while (++j < sz) {
result += arr[j] + " ";
}
result += "\n";
}
}
}

Categories

Resources