Creating a global function that withholds for loops - javascript

How do I create a for loop that can be used in other functions?
How do I create a global variable with for loops?
arrayNr1 = [4,8,13,2]
arrayNr2 = [1,2,3,13]
function globalLoop(array1, array2) {
for(var i=0; i<array1.length; i++) {
for(var j=0; j<array2.length; j++){
if(array1[i] == array2[j]) {
return array2[j]
}
}
}
}
console.log(globalLoop(arrayNr1,arrayNr2)); //-> 13
Why is it only returning 13 instead of 13 and 2?

The first time the if statement is true, the function will return.
The loop won't keep going and return more things.
A function can only return a single thing, and a return statement will stop the function from running further.
If you want to find every match, then you need to store matches somewhere (such as another array) and return after the loops have finished.

Check it:
arrayNr1 = [4,8,13,2];
arrayNr2 = [1,2,3,13];
arrayFinal = [];
function globalLoop(array1, array2) {
for(var i=0; i<array1.length; i++) {
for(var j=0; j<array2.length; j++){
if(array1[i] == array2[j]) {
arrayFinal.push(array2[j])
}
}
}
}
globalLoop(arrayNr1,arrayNr2);
console.log(arrayFinal);

You exit the function at the first find.
return array2[j]
You could collect the values with an array.
function globalLoop(array1, array2) {
var result = [], i, j;
for (i = 0; i < array1.length; i++) {
for (j = 0; j < array2.length; j++){
if (array1[i] == array2[j]) {
result.push(array1[i]);
break;
}
}
}
return result;
}
var arrayNr1 = [4, 8, 13, 2],
arrayNr2 = [1, 2, 3, 13];
console.log(globalLoop(arrayNr1,arrayNr2));

You are iterating over arrayNr1 first and the first match in both arrays is (13, 13). The return statement stops the loop on the first match, it never gets to the second.
The following snippet collects all matches and returns an array.
arrayNr1 = [4,8,13,2]
arrayNr2 = [1,2,3,13]
function globalLoop(array1, array2) {
var equal_elements = [];
for(var i=0; i<array1.length; i++) {
for(var j=0; j<array2.length; j++){
if(array1[i] == array2[j]) {
// collect matches
equal_elements.push(array2[j]);
}
}
}
return equal_elements;
}
console.log(globalLoop(arrayNr1,arrayNr2));

Related

javascript function don't pass cases

I have no idea why my function doesn't work in some cases:
function moveZeros(elem) {
var count = 0;
var a=elem;
for (var i=0; i< elem.length; i++){
if (elem[i]===0) {
elem.splice(i,1);
count++;
}
}
while (count>0) {
elem.push(0);
count--;
}
return elem;
}
In moveZeros([1,2,0,1,0,1,0,3,0,1]) all good, but if case is:
moveZeros([9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9])
it returns
[9,0,9,1,2,1,1,3,1,9,0,0,9,0,0,0,0,0,0,0]
I case :
moveZeros(["a",0,0,"b","c","d",0,1,0,1,0,3,0,1,9,0,0,0,0,9])
it returns:
["a",0,"b","c","d",1,1,3,1,9,0,0,9,0,0,0,0,0,0,0]
Why not all zeros goes to the end ?
Other ways to do this include filtering out the zeros and using Array.fill to repad with zeros at the end
function moveZeros(elem) {
var f=elem.filter(x=>x!==0);
return f.fill(0, f.length, f.length=elem.length);
}
console.log( moveZeros([9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]) );
When you're removing elements from an array while iterating over it, you need to go from the end of the list to the beginning. This is because when you .splice the element out, i is no longer pointing to the index it was previously pointing to, so it'll skip over some indices. Try this instead.
function moveZeros(elem) {
var count = 0;
var a=elem;
for (var i = elem.length - 1; i >= 0; i--){
if (elem[i]===0) {
elem.splice(i,1);
count++;
}
}
while (count>0) {
elem.push(0);
count--;
}
return elem;
}
Your problem is that when you remove an element the next item processed is the original location plus one i.e. with the array [1,0,0,1] you will process the 1 (index 0) then the first 0(index 1) and then the last 1(index 2); The second 0 was at index 2 when you started but was skipped because removing the first 0 changed it's index to 1.
To process the array correctly you want to subtract 1 from i whenever you find a match -
function moveZeros(elem) {
var count = 0;
var a=elem;
for (var i=0; i< elem.length; i++){
if (elem[i]===0) {
elem.splice(i,1);
count++;
i--;
}
}
while (count>0) {
elem.push(0);
count--;
}
return elem;
}
Why don't you do something like
function moveZeros(arr){
let idx =0;
for(let i = 0; i<arr.length; i++){
if(arr[i] == 0){
idx++;
}
else{
arr[i-idx] = arr[i];
}
}
for(let i = arr.length-idx; i< arr.length; i++){
arr[i] = 0;
}
console.log(arr);
}
moveZeros([1, 2, 3, 0, 0, 4, 5, 0, 0, 6]);
moveZeros([1,2,0,1,0,1,0,3,0,1]);
moveZeros([9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9])
it does it in one pass without having to use splice() which is costly

Uniqualize array in Javascript? [duplicate]

This question already has answers here:
Remove duplicate values from JS array [duplicate]
(54 answers)
Closed 8 years ago.
I have the following script that's supposed to uniqualize array:
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
However, when it receives only one element, it just breaks it into the letters (which is understandable).
Do you know how I make it check if it's receiving only one element and then returns it back?
Thanks!
I'm not sure why you need the nested loop - you only need a single loop if you're processing a non-nested array:
function uniques(arr) {
if (arr.length === 1) { return arr };
var a = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (a.indexOf(arr[i]) === -1) {
a.push(arr[i]);
}
}
return a;
}
DEMO
If you want to process nested arrays, use a recursive function. Here I've used underscore's flatten method as the basis:
function toType(x) {
return ({}).toString.call(x).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
function flatten(input, output) {
if (!output) { output = []; }
for (var i = 0, l = input.length; i < l; i++) {
var value = input[i];
if (toType(value) !== 'array' && output.indexOf(value) === -1) {
output.push(value);
} else {
flatten(value, output);
}
}
return output.sort(function (a, b) { return a - b; });
};
var arr = [1, 2, 3, [[4]], [10], 5, 1, 3];
flatten(arr); // [ 1, 2, 3, 4, 5, 10 ]
DEMO
I think the solution is this:
function uniques(arr) {
if (arr.length > 1) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
else
{
return arr;
}
}
What you're trying to do is a linear search on the created matrix for each item in the original one.
The solution below will accomplish this, but at a great cost. If your original matrix is 50x50 with unique values in each cell, it will take you 50^3 (=125000) loops to exit the function.
The best technique to search, in programming science, takes O(log(N)) that means that if you'll use it on your problem it will take log(50^2) (=11) loops.
function uniques(arr) {
var items = [];
var a = arr.map(function(row, i) {
return row.map(function(cell, j) {
if (items.indexOf(cell) >= 0) {
items.push(cell);
return cell;
}
});
});
}

Finding missing array in array of arrays

I need to find a missing array in an "array of arrays". I started by finding this function below (on StackOverflow):
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
// look for same thing in new array
if (CurrentArray.indexOf(PreviousArray[j]) == -1)
deselectedItem.push(PreviousArray[j]);
}
return deselectedItem;
}
This works just fine if you did something like this:
oldarray = ["hi", "ho", "hey"];
newarray = ["hi", "hey"];
Using findDeselectedItem(newarray, oldarray) would return ["ho"].
However, my content looks like this:
oldarray = [["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
newarray = [["Olivia", 16, 0], ["James", 17, 1]];
How can I adapt the function above so that it returns the missing array containing 'Liam'.
Thanks
I would make a hash with the name as a key. That would make finding missing content trivial and very fast. You can then optimize the method by not rebuilding the hash every time, but only when it's really necessary.
var oldArray = [["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
var newArray = [["Olivia", 16, 0], ["James", 17, 1]];
function findDeselectedItems(oldArray, newArray)
{
var results = [];
var hash = {};
for (var i=0; i<newArray.length; i++) {
hash[newArray[i].join(',')] = true;
}
for (var i=0; i<oldArray.length; i++) {
if (!hash[oldArray[i].join(',')]) {
results.push(oldArray[i]);
}
}
return results;
}
The problem may be that indexOf uses strict equality. I.e. if an item in the 'previous' array isn't literally also in the 'current' array, it will report it to not be in there.
You will have to iterate over the values yourself (instead of using indexOf) and check if the array contains something that is 'the same as' (but not literally the same) the array.
I.e. if I didn't explain myself well enough take a look at this;
['bob'] == ['bob']; //false
//therefore
[['bob']].indexOf(['bob']); //-1
I hope that this helps you,
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
var checkArray = PreviousArrSize[j];
// loop through 2nd array to match both array
for(var i = 0; i < CurrentArrSize; i++) {
// look for same thing in new array
if (CurrentArray[i].indexOf(checkArray) == -1)
deselectedItem.push(CurrentArray[i]);
}
}
return deselectedItem;
}
#KarelG: nice and quick solution but should it not be var checkArray = PreviousArr[j]; instead of var checkArray = PreviousArrSize[j]; ?
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
var selectedIndices = [];
// loop through previous array
for(var j = 0; j < PreviousArrSize; j++) {
for(k=0; k < CurrentArrSize ; k++){
if (CurrentArray[k].toString() === PreviousArray[j].toString()){
selectedIndices.push(j);
break;
}
}
}
for(var l = 0; l < PreviousArrSize; l++){
if(selectedIndices.indexOf(l) === -1){
deselectedItem.push(PreviousArray[l]);
}
}
return deselectedItem;
}
I don't think you can use indexOf to compare two arrays. You need a deeper comparison. Although this code could be written another way, you could do this with an array comparison function and using Array.some() to filter through your elements. Here's an example and a fiddle;
// Credit http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
// attach the .compare method to Array's prototype to call it on any array
Array.prototype.compare = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0; i < this.length; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].compare(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
function findDeselectedItem(CurrentArray, PreviousArray) {
var CurrentArrSize = CurrentArray.length;
var PreviousArrSize = PreviousArray.length;
var deselectedItem = [];
// loop through previous array
for (var j = 0; j < PreviousArrSize; j++) {
// look for same thing in new array
CurrentArray.some(function (a, idx) {
if(PreviousArray[j].compare(a) == false) {
deselectedItem.push(PreviousArray[j]);
return true;
}
});
}
return deselectedItem;
}
var oldarray =[["James", 17, 1], ["Olivia", 16, 0], ["Liam", 18, 1]];
var newarray =[["Olivia", 16, 0], ["James", 17, 1]];
console.log(findDeselectedItem(newarray, oldarray));

Compare two diff array with same size

I have a simple application in which I want compare two arrays.
function check() {
var Array1 = value.length;
var Array2 = selected_value.length;
alert(Array1 + "," + Array2);
for (var i = 0; i < Array1; i++) {
for (var j = 0; j < Array2; j++) {
if (value[i] == selected_value[j]) {
alert("both div are same");
}
}
}
}​
my arrays have 4 elements each but the if condition is not satisfied.
try to view yout values. before if write console.log( value[i], selected_valuw[j]) and check whether they are alike
Here is function, with which you can compare two arrays
function arraysEqual(arr1, arr2) {
if(arr1.length !== arr2.length)
return false;
for(var i = arr1.length; i--;) {
if(arr1[i] !== arr2[i])
return false;
}
return true;
}
Source
You can check if array return false, like this
if(!arrayEqual(arr1,arr2)) {
// false
}

how to compare two arrays of different length if you dont know the length of each one in javascript?

I am stuck in this. I got 2 arrays, I don't know the length of each one, they can be the same length or no, I don't know, but I need to create a new array with the numbers no common in just a (2, 10).
For this case:
var a = [2,4,10];
var b = [1,4];
var newArray = [];
if(a.length >= b.length ){
for(var i =0; i < a.length; i++){
for(var j =0; j < b.length; j++){
if(a[i] !=b [j]){
newArray.push(b);
}
}
}
}else{}
I don't know why my code never reach the first condition and I don't know what to do when b has more length than a.
It seems that you have a logic error in your code, if I am understanding your requirements correctly.
This code will put all elements that are in a that are not in b, into newArray.
var a = [2, 4, 10];
var b = [1, 4];
var newArray = [];
for (var i = 0; i < a.length; i++) {
// we want to know if a[i] is found in b
var match = false; // we haven't found it yet
for (var j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
// we have found a[i] in b, so we can stop searching
match = true;
break;
}
// if we never find a[i] in b, the for loop will simply end,
// and match will remain false
}
// add a[i] to newArray only if we didn't find a match.
if (!match) {
newArray.push(a[i]);
}
}
To clarify, if
a = [2, 4, 10];
b = [4, 3, 11, 12];
then newArray will be [2,10]
Try this
var a = [2,4,10];
var b = [1,4];
var nonCommonArray = [];
for(var i=0;i<a.length;i++){
if(!eleContainsInArray(b,a[i])){
nonCommonArray.push(a[i]);
}
}
function eleContainsInArray(arr,element){
if(arr != null && arr.length >0){
for(var i=0;i<arr.length;i++){
if(arr[i] == element)
return true;
}
}
return false;
}
I found this solution just using the filter() and include() methods, a very and short easy one.
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.
function compareArrays(a, b) {
return a.filter(e => b.includes(e));
}

Categories

Resources