Shift the position of an element in an array - javascript

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));

Related

Group numbers from array that are right after each other

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);

multiplying certain elements of an array javascript

var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
let doubleArray =0
for(i=array.length-2; i >= 0; i-=2) {
doubleArray= array[i]*2
}
console.log(doubleArray);
}
validateCred(valid1) //prints 8 I want it to print entire loop
Im trying to code luhn Algorithm and this is the first step of doubling every second number from the back, i want my result to equal doubleArray however when i try print it only 8 prints
you have only 8 prints because you have step i-2. Also, see comments in code about reversing an array
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
function validateCred(array) {
let doubleArray = [];
// we should move through all iterations that is why step i-=1
for(let i = array.length-1; i >= 0; i -= 1) {
// moving from the end of the array we will get reversed copy if using method push()
// that is why changed to unshift()
doubleArray.unshift((array.length - 1 - i) % 2 == 0 ? array[i] * 2 : array[i]);
// array.length - 1 - i - using because we need to move from right in case length not odd
}
console.log(doubleArray);
}
// ES6+ syntax version version
function esValidateCred1(array) {
const doubleArray = array.reverse().map((i, ind) => ind % 2 === 0 ? i*2 : i).reverse();
console.log(doubleArray);;
}
validateCred(valid1);
esValidateCred1(valid1);
You can refer the code below to get the desired output i.e. the an array with doubled value starting from back.
var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
let doubleArray = [];
for(i=array.length-2; i >= 0; i-=2) {
doubleArray.push(array[i] * 2)
}
return(doubleArray);
}
console.log(validateCred(valid1))
the easiest way is to use .map() method for array
var valid1=[4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
function validateCred(array) {
return array.map(item => item*2);
}
console.log( validateCred(valid1) ) //prints array doubled elements

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

How to sort an array starting from the middle?

Considering, I have an array like this [..., n-2, n-1, n, n+1, n+2, ...]. I would like to sort it in this way [n, n+1, n-1, n+2, n-2,...] with n equals to the middle of my array.
For example:
Input:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Output:
[5, 6, 4, 7, 3, 8, 2, 9, 1, 0]
let arrayNotSorted = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let positionMiddleArray = Math.trunc(arrayNotSorted.length / 2);
let arraySorted = [arrayNotSorted[positionMiddleArray]];
for(let i=1; i <= positionMiddleArray; i++){
if(arrayNotSorted[positionMiddleArray + i] !== undefined){
arraySorted.push(arrayNotSorted[positionMiddleArray + i]);
}
if(arrayNotSorted[positionMiddleArray - i] !== undefined){
arraySorted.push(arrayNotSorted[positionMiddleArray - i]);
}
}
console.log('Not_Sorted', arrayNotSorted);
console.log('Sorted', arraySorted);
What I have done works properly, but I would like to know if there is a better way or a more efficient way to do so ?
You could take a pivot value 5 and sort by the absolute delta of the value and the pivot values an sort descending for same deltas.
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
pivot = 5;
array.sort((a, b) => Math.abs(a - pivot) - Math.abs(b - pivot) || b - a);
console.log(...array); // 5 6 4 7 3 8 2 9 1 0
You can do that in following steps:
Create an empty array for result.
Start the loop. Initialize i to the half of the length.
Loop backwards means decrease i by 1 each loop.
push() the element at current index to the result array first and the other corresponding value to the array.
function sortFromMid(arr){
let res = [];
for(let i = Math.ceil(arr.length/2);i>=0;i--){
res.push(arr[i]);
res.push(arr[arr.length - i + 1])
}
return res.filter(x => x !== undefined);
}
console.log(sortFromMid([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
[5, 6, 4, 7, 3, 8, 2, 9, 1, 0]

Get the N elements from array based on the position

I want a function that returns the sub array which takes a position & the no. of elements I want. I think there may be some algorithm to find the pivot point or something & from that I can get the sub array, but I totally forgot it.
Example: a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I want 6 elements
if position = 0, then I want [1, 2, 3, 4, 5, 6]
if position = 1, then [1, 2, 3, 4, 5, 6]
if position = 2, then [1, 2, 3, 4, 5, 6]
if position = 3, then [1, 2, 3, 4, 5, 6]
if position = 4, then [2, 3, 4, 5, 6, 7]
if position = 5, then [3, 4, 5, 6, 7, 8]
if position = 6, then [4, 5, 6, 7, 8, 9]
if position = 7, then [5, 6, 7, 8, 9, 10]
if position = 8, then [5, 6, 7, 8, 9, 10]
if position = 9, then [5, 6, 7, 8, 9, 10]
simply get the middle of N elements based on the position I pass.
I can write up my own loop which will contain multiple if-else conditions to get it done. But I feel there may be some easy way to do it.
I didnt include my incomplete code snippet because I strongly feel there must be some algorithm to do this.
What you want is : Array.prototype.slice(...)
It's neatly documented here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
var n = 6;
var start = Math.max(0, Math.min(Math.floor(position-n/2), a.length-n));
return a.slice(start, start+n);
Simple way:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
function getSubArray(idx, _length, _array) {
return _array.slice(idx, idx + _length);
}
var subArray = getSubArray(3, 6, a);
You could use an offset for the postion and get the the start value first for slicing.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
n = 6,
i,
start;
for (i = 1; i < 12; i++) {
start = Math.max(Math.min(i - n / 2, a.length - n), 0);
console.log(i, ': ', a.slice(start, start + n).join());
}
Your only need is to check if you are not gonna check a pos that doesn't exist. Like :
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var n = 6; // Number of result you want
var x = 8; // Pos you want
// If you gonna exceed your length, we got only the n last element
if((x+(n/2)) > a.length) {
console.log(a.slice(a.length-n));
// Otherwise, if under 0, we got the n first
} else
if((x-(n/2)) < 0) { console.log(a.slice(0,n) );
// Default case
} else {
console.log(a.slice((x-(n/2)),(x+(n/2))));
}
This is not the smartest way, but he can give you some hint. I used the slice as other mentionned to avoid a lot of if, but you should do GENERIC test.
Something like this :
a = [1,2,3,4,5,6,7,8,9,10];
n = 6;
function split(position) {
var start = Math.min(Math.max(position - Math.floor(n/2), 0), a.length - n);
var stop = Math.min(start+n, a.length);
return a.slice(start, stop);
}
No need for the Math object at all. You may simply do as follows;
function getArr(a,n,d){
n = n - 4 < 0 ? 0
: a.length - d > n - 4 ? n - 3
: a.length - d;
return a.slice(n,n + d);
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
diff = 6;
for (var i = 0; i < 10; i ++) console.log(JSON.stringify(getArr(arr,i,diff)));
no need of if-else you can use arr[position] to arr[8]. have you got
function getArr(arr,position,requiredNumbers){
return arr.slice(position, position+requiredNumbers);
}

Categories