Javascript - Arrays - for-loop to forEach - javascript

Given an array of integers where every value appears twice except one, find the single, non-repeating value.
Follow up: do so with O(1) space.
1) This is incorrect, the idea is to iterate through twice and compare if any value the first time around is not equal to a the 2nd go around. If not, push the non equal value into a new array and return that.
2) Is forEach pretty much the same as a for-loop?
How could this be rewritten with a forEach?
This is not giving me the output I'd like, which for this example,
should just return 4
CODE
const nonRepeat = arr => {
let newArray = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length; j++) {
if (arr[i] !== arr[j]) {
newArray.push(arr[i])
}
}
}
return newArray
}
console.log(nonRepeat([2, 5, 3, 2, 1, 3, 4, 5, 1]));

Convert from for loop to forEach loop
for
for (let i = 0; i < arr.length; i++) { [code] }
forEach eliminates need to create the iterative variable ( for example, i) and always checks every element in the array
arr.forEach( [code] )
See Here for Additional Syntax Help

Related

Is that a valid Insertion Sort Algorithm? or is it bubble sort? I'm confused

let swapFun = (arrToSwap, indexFir, indexSec) => {
let temp = arrToSwap[indexFir]
arrToSwap[indexFir] = arrToSwap[indexSec]
arrToSwap[indexSec] = temp
}
let insertionSort = (arr, n = 0) => {
if (n === arr.length) {
return arr
}
for (let i = 1; i < arr.length; i++) {
while (arr[i - 1] > arr[i]) {
swapFun(arr, i - 1, i)
}
}
insertionSort(arr, n + 1)
return arr
}
console.log(insertionSort([5, 4, 33, 2, 8]))
It is actually Bubble Sort, but it is a bad implementation of Bubble Sort.
If you notice the for loop:
for (let i = 1; i < arr.length; i++) {
while (arr[i - 1] > arr[i]) {
swapFun(arr, i - 1, i)
}
}
it basically iterates the array, starting from index 1, to the end of the array, and for each item, it compares the item with the previous item. The comparison is made in the while loop, but it actually is not a loop (it just executes the body if item at index i-1 is bigger than item at index 1.) It can be replaced with a if statement:
for (let i = 1; i < arr.length; i++) {
if (arr[i - 1] > arr[i]) {
swapFun(arr, i - 1, i)
}
}
The for loop is executed in total n-1 times, because n=0 at the start and gets incremented each time the function gets called recursively, until it reached n=array length (this time the for loop will not be executed.) The body of the for-loop gets executed array.length-1 times (4 times in your example).
The biggest problem with this implementation, is the use of Recursion, which will use more Space (because Recursion uses a Stack). It also is not optimized regarding Time. Even if the array was already sorted, the for loop would be executed N-1 times, and its body will also be executed N-1 times. Which means that even in the Best Case (array is already sorted), this Bubble sort would have O(n^2) Time complexity, when in fact it can be O(n).
The optimized version of Bubble Sort:
const sort = array => {
let isSorted;
for (let i=0; i < array.length; i++) {
isSorted = true;
for (let j=1; j < array.length - i; j++)
if ( array[j] < array[j-1]) {
swap(array, j, j-1);
isSorted = false;
}
if (isSorted)
return;
}
}
const swap = (array, index1, index2) => {
let temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
const array = [5, 4, 33, 2, 8]
sort(array);
console.log(array);
The variable "isSorted", keeps track if array is Sorted or not. If no swaps were made, it means array is sorted, and I can stop the execution of the function.
Also note that in the inner loop: for (let j=1; j < array.length - i; j++) , we do not check the items at the "sorted part" (each time the inner loop if executed, one item goes to it's "final" index in the array and we do not need to make any comparisons with these items).
Hope this helped! Please ask if I did not explain something properly.

Grabbing String From Nested Array Using Nested Loops

I am a totally new to coding and I'm practicing loops and arrays. I created an array with multiple sub arrays that contain pairs of strings. I'm trying to pull out and isolate each string using a nested for loops.
Here is my code:
const pairs = [['Blue', 'Green'],['Red', 'Orange'],['Pink', 'Purple']];
//attempting to use nested arrays to get each string from an array
function getString(arr){
//this loop should grab each array in the list of arrays
for (let i = 0; i < arr.length; i++){
console.log(i , arr[i]);
//this should assign each sub array to a new var to be iterated over
subArr = arr[i];
} for (let j = 0; j < subArr.length; j++){
console.log(j, arr[j]);
}
};
console.log(getString(pairs));
the problem is the output is of the last for loop is : ['Pink', 'Purple'] not each color extracted from the nested loops.
What am I doing wrong here?
Mirii
You should nest the for loops like this:
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
//this should assign each sub array to a new var to be iterated over
subArr = arr[i];
for (let j = 0; j < subArr.length; j++) {
console.log(j, arr[j]);
}
}
How you have it, they'd run one after the other.
The solution is provided
:
function getString(arr) {
let arrResult = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
arrResult.push(arr[i][j]);
}
}
return arrResult;
}
You need to nest the loops, just like you are nesting the arrays. Also, unless you want to alter i or j, I suggest you use .forEach as it is more simple to work with.
Example:
pairs.forEach((pair, i) => {
pair.forEach((subPair, j) => {
console.log(j, subPair);
});
});
You may also make a variable, push to it within the pair.forEach function, and return it at the end of your root function.
I hope this answers your question, thank you for posting, and have a nice day. ;P
Your loops aren't actually nested: you close the first loop before starting the second one. Because subArr is a global varialbe (no let, const, or var keyword), it's still defined in the second loop, but that's not an ideal way to do things. You also need to log arr[i][j] rather than what you have.
This fixes those issues:
function getString(arr) {
//this loop should grab each array in the list of arrays
for (let i = 0; i < arr.length; i++){
//this should assign each sub array to a new var to be iterated over
let subArr = arr[i];
for (let j = 0; j < subArr.length; j++){
console.log(arr[i][j]);
}
}
};
getString(pairs);
Another issue you have is that you're calling console.log(getString(pairs)), but getString doesn't return anything, it's logging itself. If you want it to return, for example, a newline-delimited string of all the items, you could push items to an array and return them joined with a newline (or whatever character you want):
function getString(arr) {
let ret = []
//this loop should grab each array in the list of arrays
for (let i = 0; i < arr.length; i++){
//this should assign each sub array to a new var to be iterated over
let subArr = arr[i];
for (let j = 0; j < subArr.length; j++){
ret.push(arr[i][j]);
}
}
return ret.join('\n')
};
console.log(getString(pairs));
Nested loops themselves aren't ideal, since they're not as readable as using array methods. Using forEach takes much less code:
function getString (arr) {
arr.forEach(function (subArr) {
console.log(subArr[0])
console.log(subArr[1])
})
}
getString(pairs)
Or, more succinctly, you can use map:
function getString (arr) {
return arr.map(([ a, b ]) => `${a}\n${b}`).join('\n');
}
console.log(getString(pairs))
Even more succinctly, you can do this with [].flat():
const getString = (xs = []) => xs.flat().join('\n')
console.log(getString(pairs))

How to return the length of a contiguous subarray with specific criteria

I'm tasked with creating an array that takes another array and returns the number of contiguous subarrays for each index that fulfills the following conditions:
-The value at index i is the maximum value of the subarray
-The contiguous subarray must begin or end with i
I'm almost there but I'm missing the code to ensure that the function checks the array elements that aren't sat directly either side of i (see my code below). I think I might need some sort of recursive call that runs the if statement again while passing through the updated values of 'forward' and 'backward'. Or maybe I'm taking the wrong approach altogether.
Any ideas?
function countSubarrays(arr){
var arr = [3, 4, 1, 6, 2];
var output = [];
for (var i = 0; i < arr.length; i++){
var total = 1;
var forward = 1;
var backward = 1;
if (arr[i] >= arr[i+forward]) {
total++;
forward++;
// Some sort of recursive call here?
}
if (arr[i] >= arr[i-backward]){
total++;
backward++;
// Some sort of recursive call here?
}
output.push(total);
}
console.log(output);
}
countSubarrays();
You need to go backwards or ahead and count the items who are smaller or equal to the actual element.
function countSubarrays(array) {
var output = [];
for (let i = 0; i < array.length; i++) {
let value = array[i],
total = 1;
j = i;
while (j-- && value >= array[j]) total++;
j = i;
while (++j < array.length && value >= array[j]) total++;
output.push(total);
}
return output;
}
console.log(countSubarrays([3, 4, 1, 6, 2]));

Big O time efficiency for a quadratic function in JavaScript

I am trying to increase the efficiency of a function. It is currently quadratic and I would like to make it logarithmic.
The third to last line of the current function is confusing me somewhat as well and I would like some clarification.
function solution(arr){
let result = 0
for ( let i = 0; i < arr.length; i++)
for (let j = 0; j < arr.length; j++)
if (arr[i] == arr[j])
result = Math.max(result, Math.abs(i - j));
return result;
}
How do I solve this problem?
At least, you could change the indices for looping and omit self checking and to check the same pairs again.
function solution(arr){
let result = 0
for (let i = 0; i < arr.length - 1; i++)
for (let j = i; j < arr.length; j++)
if (arr[i] === arr[j])
result = Math.max(result, Math.abs(i - j));
return result;
}
The shortest approach is O(n) by taking an hash table for storing the first found index for a value.
function solution(array) {
var hash = {};
return array.reduce(
(m, v, i) => Math.max(m, i - (hash[v] = v in hash ? hash[v] : i)),
0
);
}
var array = [1, 3, 4, 5, 1, 3, 4, 5, 6, 2, 3];
console.log(solution(array));
In the above function, the goal is to find the maximum number from array. Now the meaning of third to last line which is result = Math.max(result, Math.abs(i - j)); , I will break it into two parts to explain here,
First of all, Math.abs(i-j) will be executed and provide the absolute value from the difference between i and j.
After this, the outer function Math.max() method will be called which will provide you the maximum value between result and absolute value obtained from first step. Now the maximum value will be store in result. This is how the function is working.
Now this statement is conditional based, which means it will only execute if arr[i]==arr[j].
I hope it cleared the work flow of this program.

Delete Record From Javascript Array Object

i have a java script array object and i want to delete items from a specific index in that object, i have a comma separated string of that indexes. problem is that when i delete it using splice array indexes got changed, and other indexes's object not got deleted.
var DeletedConditions="3, 5, 19, 50";
for (var k = 0; k < DeletedConditions.split(", ").length; k++) {
ConditionObject.splice(DeletedConditions.split(", ")[k], 1);
}
DeletedConditions string can be anything.
please help me out. how to get this done.
First of all, I suggest you officially turn the indexes into a formal array. Having a string as an index reference, you are prone to missing a split shall there be a case where the values are not separated by ,
Then the code:
var content = ['foo', 'bar', 'baz', 'bam', 'dom', 'zok'],
deleteIndexes = [5, 1, 3],//should delete zok, bar, bam
i;
//sort from least to greatest: [1, 3, 5]
deleteIndexes.sort(function(a, b) {
return a - b;
});
//we loop backwards (performance enhancement)
//now we loop from greatest to least
//we now splice from greatest to least
//to avoid altering the indexes of the content as we splice
for (i = deleteIndexes.length; i-- > 0;) {
content.splice(deleteIndexes[i],1);
}
console.log(content); //["foo", "baz", "dom"]
​
You can always decrement the k iterator after splicing inside the loop:
k--;
var DeletedConditions="3, 5, 19, 50";
var list = DeletedConditions.split(", ")
for (var k = 0; k < list.length; k++) {
// using splice here
list.splice(k,1);
k--;
}
console.log(list.join(', '))
Removing an item from the beginning of the array shuffles the later elements up and changes their indices, as you've observed. But if you go through the list of items to remove backwards then it will remove the later elements first so the indices will still be correct for the elements closer to the beginning of the array.
Also, please don't do the .split() operation on every loop iteration - the inefficiency might not make much difference on a string with four numbers in it, but it makes the code kind of messy and on principle it is just kind of yucky.
var DeletedConditions="3, 5, 19, 50",
delCondArr = DeletedConditions.split();
for (var k = delCondArr.length - 1; k >= 0; k--) {
ConditionObject.splice(delCondArr[k], 1);
}
If there's a possibility that the DeletedConditions strig might not be ordered just add a .sort() after you split it:
delCondArr = DeletedConditions.split().sort(function(a,b){return a-b;});
...in which case you don't need to loop backwards.
It might be easiest to copy the original array, omitting the deleted items in the process. Something like this would do the trick...
var DeletedConditions="3, 5, 19, 50";
DeletedConditions = DeletedConditions.split(', ');
var newConditionObject = [];
for(var k = 0; k < ConditionObject.length; ++k) {
if(DeletedConditions.indexOf(k) !== -1) { continue; }
newConditionObject.push(ConditionObject[k]);
}
// result is in `newConditionObject`
console.log(newConditionObject);
var fruits = new Array("apple", "banana", "grapes", "oranges","mosambi","aaa","bbb","ccc");
var DeletedConditions="1,3,4,5";
var indexArray = new Array;
indexArray = DeletedConditions.split(",");
for (var i = 0; i < indexArray.length; i++) {
fruits.splice(indexArray[i], 1);
}

Categories