Group numbers from array that are right after each other - javascript

I have an array with some numbers like the following:
[1, 2, 3, 4, 6, 7, 8, 10, 15, 16, 17]
I'd like to show all numbers that are direct after each other (n+1) in one line and if there is a gap, this should be separated. This will either be done in javascript/jquery.
The user would see it like this:
1 - 4, 6 - 8, 10, 15 - 17
I'm guessing the only solution to this would be to loop through the array and see if the next number is n+1 and if it is, lump it together, else start on a new series?
I think I know how I would do it that way but interested to know if there is some other way to do it either in javascript/jquery?

You can loop once while keeping track of the current starting number.
let arr = [1, 2, 3, 4, 6, 7, 8, 10, 15, 16, 17];
let start = arr[0],
res = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i + 1] - arr[i] != 1 || i == arr.length - 1) {
res.push(start + " - " + arr[i]);
start = arr[i + 1];
}
}
console.log(res);

Related

If statement do not work with modulo. Can't get the console.log() to write out anything. I am using a const with a variable

My task is like this:
You will see the array 'numbers'. Use a for loop to go through that array. For each element in the array, print the number to the console using console.log. If the number is divisible by 3, instead of the number print the string 'apple' to the console. Should the number be divisible by 5, print the string 'cake' to the console instead of the number.
In the first task, I used a for loop to show every number from 1-20, so I can't seem to understand why I can't get this to work. I am maybe thinking I have to implement a new for loop in this task too.
My code is like this:
console.log('PART 3')
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
if (numbers % 3){
console.log('eple');
}
else if(numbers % 5){
console.log('kake');
}
You cannot use modulo (Reminder Operator %) on an array.
You're missing a for loop (as stated by the task requirement) in order to iterate over its values:
console.log('PART 3')
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
for (let number of numbers) {
if (number % 3){
console.log(number + ' eple');
}
else if(number % 5){
console.log(number + ' kake');
}
}
In order to find out if a number is a factor of another number:
number % 3 === 0
That translates as: If a number divided by 3 has a remainder of 0...
You don't even have a for loop
for (let i=0; i < array.length; i++) {...}
There are 3 expressions of a for loop statement
Expression
Example
Description
Initial
let i=0
Define variable at the beginning
Condition
i < array.length
When variable no longer less than the quantity of elements within the array stop loop
Increment
i++
Variable increments by 1
Flow control statements can be only in a certain order:
if (a > b) {...}
// OR
if (a > b) {...}
else {...}
// OR
if (a > b) {...}
else if (a === b) {...}
// ...more else if(...){...} if required
else {...}
Never do this
if (a > b) {...}
else if (a === b) {...}
// This will create an array of 1 - 20 programatically
const array = [...Array(20)].map((_, i) => i + 1);
console.log(JSON.stringify(array));
for (let i = 0; i < array.length; i++) {
let number = array[i];
if (number % 3 === 0) {
console.log("APPLE");
} else if (number % 5 === 0) {
console.log("CAKE");
} else {
console.log(number);
}
}
console.log('PART 3')
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
const output = [];
for(i=numbers[0];i<=numbers.length;i++){
if(numbers[i]%3==0 && numbers[i]%5==0){
output.push(numbers[i] + " :Apple, Cake")
console.log(output);
}
else if(numbers[i]%5==0){
output.push(numbers[i] + " :Cake")
console.log(output);
}
else if(numbers[i]%3==0){
output.push(numbers[i] + " :Apple")
console.log(output);
}
}

Why is splicing an array in JavaScript removing the last few elements?

I'm currently working on an array function that converts subarrays of consecutive numbers into strings denoting that range of numbers — for example, this array...
[1, 2, 3, 6, 8, 10, 11, 12, 15, 18]
...would become this array:
["1-3", 6, 8, "10-12", 15, 18]
I've been able to develop a function that mostly works, but I've encountered a weird error where all the elements past the final range of numbers spliced into the array are completely deleted. For example, the test array above actually becomes this:
["1-3", 6, 8, "10-12"]
This is the code I've written so far. It's not super pretty yet, but as I mentioned above, it gets the job done right up until the very end:
let testArray = [1, 2, 3, 6, 8, 10, 11, 12, 15, 18];
for (i = 0; i < testArray.length; i++) {
let consecutives = [];
consecutives.push(testArray[i]);
let j = i + 1;
while (j < testArray.length) {
if (testArray[j] == (testArray[j - 1] + 1)) {
consecutives.push(testArray[j]);
j++;
} else {
break;
}
}
if (consecutives.length > 2) {
let range = String(testArray[i]) + "-" + String(testArray[j - 1]);
console.log(testArray);
console.log(testArray[i]);
console.log(testArray[j]);
testArray.splice(i, j, range);
}
}
console.log(testArray);
These are the console logs output by that code:
Array(10) [ 1, 2, 3, 6, 8, 10, 11, 12, 15, 18 ]
1
6
Array(8) [ "1-3", 6, 8, 10, 11, 12, 15, 18 ]
10
15
Array(4) [ "1-3", 6, 8, "10-12" ]
I initially figured this was caused by a mix-up with array indexes, but playing around with the index-1s hasn't fixed the problem yet. Has anyone else ever had a similar issue with JavaScript's splicing, and if so, how were you able to get it working?
The problem lies in one line of code:
testArray.splice(i, j, range);
According to the MDN, the second argument specifies how many elements in the array to delete.
deleteCount
An integer indicating the number of elements in the array to remove from start.
However, the code defines this argument as the index of the last array to remove from:
let j = i + 1;
The solution is to get the difference between i and j before passing it to splice:
testArray.splice(i, j - i, range);
When you do:
testArray.splice(i, j, range);
You are forgetting that j is the right limit index of the array that you want to erase, so you need to subtract i that is the left limit:
testArray.splice(i, j - i, range);
let testArray = [1, 2, 3, 6, 8, 10, 11, 12, 15, 18];
for (i = 0; i < testArray.length; i++) {
let consecutives = [];
consecutives.push(testArray[i]);
let j = i + 1;
while (j < testArray.length) {
if (testArray[j] == (testArray[j - 1] + 1)) {
consecutives.push(testArray[j]);
j++;
} else {
break;
}
}
if (consecutives.length > 2) { // doesn´t it should be > 1 ??
let range = String(testArray[i]) + "-" + String(testArray[j - 1]);
console.log(testArray);
console.log(testArray[i]);
console.log(testArray[j]);
testArray.splice(i, j - i, range);
}
}
console.log(testArray);

JavaScript - reverse an array in a specific way

I'm doing an algorithm course and here is the instructor's answer about how to reverse an array without using reverse js method:
function solution(arr) {
for(var i=0; i < arr.length/2; i++) {
var tempVar = arr[i]
arr[i] = arr[arr.length - 1 - i]
arr[arr.length - 1 - i] = tempVar
}
return arr
}
I did understand everything, EXCEPT this detail:
arr.length/2
In this line below:
for(var i=0; i < arr.length/2; i++) {
what does it mean? What its purpose?
To reverse a string, you have to swap characters of first half of the string with the last half.
let str = 'abcde';
You have to swap a with e, b with d.
ab is the first half of the string. So simply run loop over the first half of the string and swap ith character with arr.length - 1 - ith character as below
var tempVar = arr[i]
arr[i] = arr[arr.length - 1 - i]
arr[arr.length - 1 - i] = tempVar
Algorithm start with first and last element and swap them. Next it take the second element from the begin and from the end and swap them. And etc it swap all the elements with same distance from center.
So algorithm go to the center of array from both sides. And it need only half of length of array from both side to proceed. So that statement arr.length/2 actually the expression which is a half of length.
Which is used as limit of the loop.
The algorithm swaps two elements that are on equal distance from both ends of the array. The number of operations needed is number_of_operations = number_of_elements / number_elements_operated_on and since it's doing two elements at once, that's number_of_elements / 2. And hence the reason to use arr.length / 2 as the limit of the for loop. Here is a representation of what happens.
Given an array [1, 2, 3, 4, 5, 6] then array.length is 6 and the following operations are performed:
//loop i = 0, 0 < 3 == true, execute
[1, 2, 3, 4, 5, 6] -> [6, 2, 3, 4, 5, 1]
^--------------^ ^--------------^
//loop i = 1, 1 < 3 == true, execute
[6, 2, 3, 4, 5, 1] -> [6, 5, 3, 4, 2, 1]
^--------^ ^--------^
//loop i = 2, 2 < 3 == true, execute
[6, 5, 3, 4, 2, 1] -> [6, 5, 4, 3, 2, 1]
^--^ ^--^
//i = 3, 3 < 3 == false, loop stops
This works perfectly fine with odd number of elements, since there is going to just be one element in middle when you get to it.
Given an array [1, 2, 3, 4, 5] then array.length is 5 and the following operations are performed:
//loop i = 0, 0 < 2.5 == true, execute
[1, 2, 3, 4, 5] -> [5, 2, 3, 4, 1]
^-----------^ ^-----------^
//loop i = 1, 1 < 2.5 == true, execute
[5, 2, 3, 4, 1] -> [5, 4, 3, 2, 1]
^-----^ ^-----^
//loop i = 2, 2 < 2.5 == true, execute
[5, 2, 3, 4, 1] -> [5, 4, 3, 2, 1]
^ ^
//i = 3, 3 < 2.5 == false, loop stops

Shift the position of an element in an array

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const output = move(numbers, 3, -5);
console.log(output);
function move(array, index, offset) {
const output = [...array];
const element = output.splice(index, 1)[0];
output.splice(index + offset, 0, element)
return output;
}
The first line is an array of numbers.
At the second line, when calling the move function, we pass three arguments.
First, is the array itself called numbers.
Secondly, the index of the number we are trying to move (in the example, we have index 3 so we are passing the number 4).
Finally, we have the offset set to -5. The negative sign means we are moving the number to the left. The 5 means 5 positions.
But as you can see, we only have 3 positions to the left of the number 4 before reaching the beginning of the array. In this case, we have to go to the end of the array and count backwards. So, we are looking for a function which will turn the original array to [1, 2, 3, 5, 6, 7, 8, 4, 9].
As you can see, number 4 has shifted 3 positions to the left to reach the beginning of the array, then, 2 further positions from the end of the array.
A further example to clarify.
Let's say we write:
const output = move(numbers, 1, -4);
In this example, we want the number 2 from the array (index 1) to move 4 positions to the left. So, we should get [1, 3, 4, 5, 6, 7, 2, 8, 9].
You need to cover the edge cases when the updated index is less than 0 OR greater than the array length. You can try following
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function move(array, index, offset) {
const output = [...array];
const element = output.splice(index, 1)[0];
let updatedIndex = index + offset;
if(updatedIndex < 0) updatedIndex++;
else if (updatedIndex >= array.length) updatedIndex -= array.length;
output.splice(updatedIndex, 0, element);
return output;
}
console.log(move(numbers, 3, -5));
You could do this using while loop and iterating for the Math.abs() of the position you want to move to and then move in direction depending if parameter is positive or negative.
function move(arr, i, p) {
let left = p < 0,
counter = Math.abs(p),
newPos = i;
while (--counter > -1) {
newPos = (left ? (newPos - 1) : (newPos + 1));
if (newPos == -1) newPos = arr.length - 1;
if (newPos == arr.length) newPos = 0;
if (counter == 0) arr.splice(newPos, 0, arr.splice(i, 1)[0])
}
return arr;
}
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, -5));
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 5, 5));
console.log(move([1, 2, 3, 4, 5, 6, 7, 8, 9], 1, -25));

Get X numbers from arrayA[5000] into arrayB[] in groups

I have an array like this:
arrayA = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,1,2];
I need to get separated numbers in groups like this:
arrayB = [1234,5678,9123,4567,8912];
As you can see its the same arrayA but in groups of 4 values that are now new numbers.
I was able to make it work with a bug like this: arrayB=[undefined1234,undefined5678];
with this code:
for (var i = 0; i < 20; i++) {
if (i/4== n+1){
arrayB[n] = temp;
n++;
}
temp += arrayA[i];
}
And thats it. I understand the bug, it is because of that += but am not sure how to do this any other way.
this code will do that trick
var arrayA = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2,3,4];
var arrayB = [];
for (var x = 0; x < arrayA.length; x += 4) {
arrayB.push(arrayA.slice(x, x + 4).join(''));
}
console.log(arrayB);
Update
Millie has raised a fair point. if you need numbers in the result array, use following statement in for loop
arrayB.push(parseInt(arrayA.slice(x, x + 4).join('')));
Try setting temp to "" both before the loop starts and after each time you assign to arrayB (and when you make that assignment, turn the string in step into an integer). And you may need to make a final assignment to arrayB after the for loop finishes.
I would do it like this:
arrayA = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2];
temp = arrayA.join('');
count = 4;
grouped = [];
max = temp.length / count;
for (i = 0; i < max; i++) {
grouped.push(parseInt(temp.substr(i * 4, 4)));
}
console.log(grouped);
Little numbers to strings conversion, and returning of numbers. :)
Demo: http://jsfiddle.net/hue0a1wb/

Categories