I am trying to write code that reverses an array in place without using the reverse function (I'm busy learning JS so just doing an exercise from Eloquent JavaScript).
function reverseArrayInPlace(arr) {
for (let i = 0; i < arr.length; i++) {
arr[i] = arr[(arr.length - 1) - i];
}
return arr;
}
This was the code that I wrote which doesn't quite work, I know this is because I have already reassigned arr[0] and arr[1] so if I call reverseArrayInPlace([1, 2, 3, 4 ,5]), [5, 4, 3, 4, 5] is returned.
This was given as the solution:
function reverseArrayInPlace(array) {
for (let i = 0; i < Math.floor(array.length / 2); i++) {
let old = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = old;
}
return array;
}
Could anyone please explain what's happening in the solution so I can better understand? Thanks :)
So here is what is happening in this function:
for(let i = 0; i < Math.floor(array.length / 2); i++):
they are using the Math.floor() method to make sure that you only iterate through half of the array. That is why your original solution repeated elements instead of reversing them.
let old = array[i]:
This is a temporary variable to hold the element at the current index in the loop while you swap them.
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = old;
this swaps the elements.
which only leaves return array;
You only need to loop over half of the array since you are swapping items; if you loop over the entire array, you will swap each item twice, not changing the array at all. In each iteration, you just copy over the value at the reflected index, instead of transposing the two values, for which you need a temporary variable to store one of the values.
Say you have an array [1, 2, 3, 4, 5]. The code starts from left most element, and swap it with the right most element. so you get [5, 2, 3, 4, 1]. Then it does the same for the next element in the array, swap it with the second to right element, and you'll get [5, 4, 3, 2, 1]. Math.floor(array.length) make sure that the already swapped elements don't swap again, so it will only go through the first half of the array.
Related
Hi fam happy Valentine's.
I'm not looking for a code solution but some insights about how could I go about iterating over an array let's call it array = [1, 1, 1], and not moving to the next element in the array until a condition is fulfilled. For example I want to start at index 0 and only go to the next index (1) after the value of such index is (modified/changed) to be greater than the value of the index before it. At 0 index we have the value 1, I want before moving to index 1 to change the value of index 1 to be greater then the value of index 0. Something like this if we have array = [1, 1, 1] I want to iterate over the array, start at 0 index. Compare if the value of 0 index is greater or equal than the value of index 1 (the next index) If so than add 1 to the value of index 1 until that value is greater than the value of index 0. First iteration we get array = [1, 2, 1].
Next iteration we get array = [1, 2, 3].
At this point I have tried to iterate over the array with a for loop grab each element, compare and add 1 to the element but when I get to the last element it does not add anything since I am at the end of the array and there is no item to loop over. I get array = [1, 2, 2] Please help fam. This is what I have so far.
// array
const array = [1, 1, 1]
// iterating over array
for (let i = 0; i < array.length; i++) {
// compare
if (array[i] >= array[i + 1]) {
// increase next number by 1
array[i + 1] += 1
}
}
You could start from index 1, because you can not change the value at index 0 because of the missing previous value.
Inside the loop increment the value until it is greater than the value at the last index.
const array = [1, 1, 1]
for (let i = 1; i < array.length; i++) {
while (array[i] <= array[i - 1]) array[i]++;
}
console.log(array);
If you don't want to iterate for the increment, you could update the value directly.
const array = [1.2, 1, 1]
for (let i = 1; i < array.length; i++) {
if (array[i] <= array[i - 1]) array[i] = Math.floor(array[i - 1] + 1);
}
console.log(array);
Happy Valentines!
Let's look at what may be causing your array to return [1,2,2]. Good practice (And a bit tedious) is to follow along your inputs and see item by item how your array gets manipulated.
input: [1,1,1]
First Pass: [1,1,1], changes to [1,2,1]
Second Pass:[1,2,1] changes to [1,2,2]
You may have noticed the undesired behaviour happens on the second pass. It's because you're adding 1 to the value and not incrementing based on the index you're on.
Now.. lets get to fixing!
If we assume your input is always [1,1,1] (ASSUMPTIONS MATTER :) )
you can simply change array.
array[i + 1] += 1 to array[i+1] += array[i]
If you're looking for a more comprehensive approach where you can take any array input, sort and display an incrementing array -- that's a little further ahead! Focus on the fundamentals :)
This question already has answers here:
JS: Reverse an Array but Reverse the Original Array Only --> Error: running with no output
(6 answers)
Reversing an array in javascript?
(3 answers)
Reversing an array without 'reverse' or duplicating an array
(10 answers)
Closed 1 year ago.
I want to use the same variable array to output the reverse an integer array. But, I only got the first value print out. Not sure where I did wrong.
Here is my code:
let array = [3, 8, 9, 6, 4, 2]
reverseArray(array);
function reverseArray(array){
let left =0;
for(i = 0; i <= array.length - 1; i++){
let right = array.length - 1 - i;
let temp = right;
right = left;
left = temp;
array = array[left];
}
console.log(array);
}
Assuming this is a learning exercise, note that you are iterating too many times:
function reverseArray(array){
const len = array.length;
for (let i = 0; i < len/2; ++i) {
const temp = array[i];
const tail = len - i - 1;
array[i] = array[tail];
array[tail] = temp;
}
}
const array = [3, 8, 9, 6, 4, 2];
reverseArray(array);
console.log(array);
As others have pointed out, the reason for truncation is the fact that you assigned an array element to the array variable, turning it from an array into a scalar.
"In real life", you should use array.reverse().
it's because you set the array as a single value by doing array = array[left].
you just override the array variable and placing a single element inside it.
changing this line to array[right] = array[left] would be a good start.
if you want to fix it all, you need to iterate only through HALF of the array (so that you won't reverse it twice - back to normal), and make the whole swap (not just replace one element):
let array = [3, 8, 9, 6, 4, 2]
reverseArray(array);
function reverseArray(array){
for(i = 0; i < array.length / 2; i++){
let right = array.length - 1 - i;
let temp = array[right];
array[right] = array[i];
array[i] = temp;
}
console.log(array);
}
Note: if you want to reverse an array you can simply use the array prototype "reverse" function like this:
let array = [3, 8, 9, 6, 4, 2];
array = array.reverse();
console.log(array);
Actually you changing index so right use to store index not value and in the last line array = array[left] is you are trying to give value and that is array[0] = 1 so that's why 1 is coming
Right way to do this
let array = [3, 8, 9, 6, 4,2]
reverseArray(array);
function reverseArray(array){
for(i = 0; i <= (array.length - 1)/2; i++){// need to iterate only half otherwise it remain same so for exampale 0th index replace with 4th index and 4th with 0 so at last both at their same position
let right = array.length - 1 - i;
let temp = array[right];
array[right] = array[i];
array[i] = temp;
}
console.log(array);}
Just use build in NodeJs function:
array.reverse()
What you are actually doing wrong is
array = array[left]
On the right side of this equation is a value of array at a specific index while on the right side of this array is a whole array
First off, here's the algorithm:
var removeDuplicates = function(nums) {
for (var i = 0; i < nums.length;) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, 1)
}
else i++
}
return nums
};
It takes in a sorted array of numbers and removes any duplicates to return the original array modified to only include unique numbers.
My question mainly concerns the usage of the for loop. In this for loop we are omitting the third statement and instead are incrementing i in the else condition.
How does the loop know to check the next index of nums if the if condition is fulfilled? Ie. if we never hit else, how is i incremented? Is it even incremented? I understand this may have something to do with the fact that we are splicing (therefore shortening) the nums array in the if condition but I am having a hard time fully grasping why the loop does not end as soon as the if statement is fulfilled once.
When you do
nums.splice(i, 1)
this removes 1 item from the array at index i. For example, if i is 2, and the current array is
[0, 1, 2, 2, 3, 4]
then, right after that splice occurs, the array becomes
[0, 1, 2, 2, 3, 4]
^^ REMOVED: Array mutates to
[0, 1, 2, 3, 4]
The item that used to be at index i + 1 is now at index i, so the next iteration of the for loop should not increment i.
If you did increment i regardless, then every item that comes immediately after a removed item would be skipped, and not iterated over at all:
var removeDuplicates = function(nums) {
for (var i = 0; i < nums.length; i++) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, 1)
}
}
return nums
};
console.log(removeDuplicates([0, 1, 1, 1]));
Still, this style of code is very confusing: when an object changes while you're iterating over it, it can be pretty unclear what the logic being implemented in accomplishes. Better to deduplicate via a Set:
var removeDuplicates = nums => [...new Set(nums)];
console.log(removeDuplicates([0, 1, 1, 1]));
I have a javascript array
And i wish to get the next preceeding two elements using a function and slice.
I'm not getting the result. Is there any way to go around this?
var arr = [1,2,3,4,5,6,7,8,9]
function get(arr){
for(var i=0; i<arr.length; i++){
console.log(arr.slice(i, 3))
}}
// Now when I call the function
get(arr)
// Funny output
[1, 2, 3]
[2, 3]
[3]
[]
[]
[]
[]
[]
[]
[]
[]
You need the index instead of the length with Array#slice
Syntax
arr.slice([begin[, end]])
...
end Optional
Zero-based index before which to end extraction. slice extracts up to but not including end.
For example, slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
A negative index can be used, indicating an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence.
If end is omitted, slice extracts through the end of the sequence (arr.length).
If end is greater than the length of the sequence, slice extracts through to the end of the sequence (arr.length).
function get(arr) {
for (var i = 0; i < arr.length; i++) {
console.log(arr.slice(i, i + 3));
}
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
get(arr);
The second parameter to slice() is end index. So what you're saying is give me all elements from i to index 3 (not-inclusive).
What you should be saying is slice(i, i+3)
slice(i, 3) basically means you want a new array with elements between the index before index i and index 3. You can just use a simple for loop instead to return the proceeding two elements of each element like this:
var arr = [1,2,3,4,5,6,7,8,9]
function get(x){
for (i = 0; i < x.length - 2; i++){
console.log("The proceeding two elements of " + x[i] + " is " + x[i+1] + " and " + x[i+2]);
}
}
get(arr);
N.B. The - 2 in the for loop's x.length - 2 is to prevent returning an undefined result since the last two elements won't have two proceeding elements.
Or if you prefer using slice(), you can do this:
var arr = [1,2,3,4,5,6,7,8,9]
function get(x){
for (i = 0; i < x.length - 2; i++){
console.log(x.slice(i, i+3));
}
}
get(arr);
Again, the - 2 in the for loop's x.length - 2 is to prevent returning an undefined result or an incomplete result since the last two elements won't have two proceeding elements.
I am having trouble with a problem and how to address it. Mind you, I am relatively new to JavaScript and the problem feels like I am over complicating it.
The problem:
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Example
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
Thanks for all your comments! I wanted to update this to be a better question, and also inform you I have found a solution if someone would like to check it and see if there is a cleaner way to put it. :)
function almostIncreasingSequence(sequence) {
if(sequence.length == 2) return true;
var error = 0;
for(var i = 0; i < sequence.length - 1; i++){
if(sequence[i] >= sequence[i+1]){
var noStepBack = sequence[i-1] && sequence[i-1] >= sequence[i+1];
var noStepFoward = sequence[i+2] && sequence[i] >= sequence[i+2];
if(i > 0 && noStepBack && noStepFoward) {
error+=2;
}else{
error++;
}
}
if(error > 1){
return false;
}
}
return true;
}
Think about what your code:
sequence[i+1] - sequence[i] !== 1, variable++;
would do for the following array:[1,2,3,8,8].
From the problem description, it is not clear weather the program must remove one character. But if that is the case, the code below should do it.
function canGetStrictlyIncreasingSeq(numbers) {
var counter = 0;
var lastGreatestNumber = numbers[0];
for (var i = 1; i < numbers.length; i++) {
if (lastGreatestNumber >= numbers[i]) {
counter++;
lastGreatestNumber = numbers[i];
} else {
lastGreatestNumber = numbers[i];
}
}
if (counter <= 1)
return true;
return false;
}
var nums1 = [1, 2, 3, 4, 5]; //true
var nums2 = [1, 2, 2, 3, 4]; //true
var nums3 = [1, 3, 8, 1, 9]; //true
var nums4 = [3, 2, 5, 6, 9]; //true
var nums5 = [3, 2, 1, 0, 5]; //false
var nums6 = [1, 2, 2, 2, 3]; //false
var nums7 = [1, 1, 1, 1, 1]; //false
var nums8 = [1, 2]; //true
var nums9 = [1, 2, 2]; //true
var nums10 = [1, 1, 2, 3, 4, 5, 5]; //false
var nums11 = [10, 1, 2, 3, 4, 5]; //true
var nums12 = [1, 2, 3, 4, 99, 5, 6]; //true
console.log(canGetStrictlyIncreasingSeq(nums1));
console.log(canGetStrictlyIncreasingSeq(nums2));
console.log(canGetStrictlyIncreasingSeq(nums3));
console.log(canGetStrictlyIncreasingSeq(nums4));
console.log(canGetStrictlyIncreasingSeq(nums5));
console.log(canGetStrictlyIncreasingSeq(nums6));
console.log(canGetStrictlyIncreasingSeq(nums7));
console.log(canGetStrictlyIncreasingSeq(nums8));
console.log(canGetStrictlyIncreasingSeq(nums9));
console.log(canGetStrictlyIncreasingSeq(nums10));
console.log(canGetStrictlyIncreasingSeq(nums11));
console.log(canGetStrictlyIncreasingSeq(nums12));
Lets take a step back and think about the problem: "Given a sequence of Integers as an array" - we're dealing with arrays of data...but you already knew that.
"determine whether it is possible to obtain a strictly increasing sequence" ok, we need to make something that checks for valid sequence.
"by removing no more than one element from the array." so we can try plucking each element one-by-one and if at least one resulting array is sequential, its possible.
Now instead of one large problem we have two smaller ones
First, we're dealing with arrays, so avail yourself to JavaScript's built-in Array functions to make things easier. In the below, we use 'every()', 'forEach()', 'splice()', 'push()', and 'some()' You can read into how they work here https://www.w3schools.com/jsref/jsref_obj_array.asp It's not long and well worth your time.
Lets deal with the first problem: Determining if an array is sequential. The below function does this
function checkSequence(inputArray){
return inputArray.every(function(value, index, arr){
if (index == 0 && value < arr[index + 1]) {return true}
else if (index < arr.length && value < arr[index + 1] && value > arr[index - 1]) {return true}
else if (index = arr.length - 1 && value > arr[index - 1]) {return true}
else {return false}
});
}
It takes an input array, and uses an Array built-in function called every(), which runs a test on each element in an array
and returns 'true' if all the elements test true. Our test expects the first element to always be lower less than the second
for any given element to be greater than the previous, and less than the next, and for the last element to be greater than the next-to-last
if any element does not satisfy this test, the whole thing returns false
Now we have a means of seeing of an array is sequential, which will make the next part much easier
Now we make another function to pluck out individual elements and see if anythign works
function isPossible(input){
var results = []; //we will store our future results here
input.forEach(function(value, index, arr){
copy = Array.from(arr); //we work on a copy of 'arr' to avoid messing it up (splice mangles what you give it, and we need the un-maimed version for later iterations)
copy.splice(index, 1); //remove an element from copy (a copy of 'arr')
results.push(checkSequence(copy)); //see if it is still in sequence
});
return results.some(function(value){return value});
}
We first make an array to store the results of each attempt into the array 'results' we will use it later.
Then, we take a supplied array 'input' and use "forEach()", which performs a function with each element in an array.
for each element, we make a new array with that element removed from it, and we run the "checkSequence()"
function we made before on it, and finally store the result in the results array.
When the forEach is done, we take the results array and use 'some()' on it, which works just like 'every()'
only it returns true if at least one value is true
Now, you simply call isPossible(your_array) and it will satisfy the problem
Taking into account Patrick Barr's suggestion and assuming that es6 and arrow functions are fine, this solution using Array.prototype.filter could work. The filter itself will return array of elements that should be removed to satisfy conditions of the problem:
UPDATED
function isSequential(array) {
return array && array.length > 0 ? array.filter((x,i) => x >= array[i + 1] || array[i + 1] <= array[i - 1]).length < 2 : false;
}
console.log(isSequential([1]));
console.log(isSequential([1,2,4,5,6]));
console.log(isSequential([1,2,2,3,4,5,6]));
console.log(isSequential([1,4,3,2,5,6]));
console.log(isSequential([1,2,3,4,5,6]));
console.log(isSequential([1,2,0,3,4]));
console.log(isSequential([1,1]));
console.log(isSequential([1,2,0,1,2]));
console.log(isSequential([1,2,3,1,2,3]));
console.log(isSequential([]));
console.log(isSequential([1,0,0,1]));
console.log(isSequential([1,2,6,3,4])); //should be true, but return false