Related
I'm a new javascript developer from lua and I have some confusion about arrays. I'm trying to build a simple 2d array but after the initialization I keep getting an error that the array is "undefined"
here's the code :
var board = [];
function initBoard(){
for (var i = 0; i < 8; i++){
board.push([]);
for (var j = 0 ;i < 8; i++){
board[j].push([]);
}
}
}
function checkSquare(x, y){
if (typeof(board[x][y]) === ""){
return false;
} else {
return true;
}
}
initBoard();
console.log(checkSquare(3, 3));
Here's the error : Cannot read property '3' of undefined`
You need not only take a look to the loops, but also to the check of the value of an item of the array. The comparison with the result of typeof with an empty string is always false, because there is no data type in Javascript Which is an empty string.
For comparing the value, you could check with the value directly with a Identity/strict equality operator ===. This checks the type of the left and right side and the value as well. For objects, it check if the object has the same reference.
function initBoard() {
var board = [];
for (var i = 0; i < 8; i++) {
board.push([]);
for (var j = 0; j < 8; j++) {
board[i].push('');
}
}
return board;
}
function checkSquare(x, y) {
if (board[x][y] === '') { // check if the item is an empty string
return false;
} else {
return true;
}
}
var board = initBoard();
console.log(checkSquare(3, 3));
There's a little mistale you've made while initialising. You've misplaced j with i. Try this:
var board = [];
function initBoard(){
for (var i = 0; i < 8; i++){
board.push([]);
for (var j = 0 ;j< i; j++){ //There was a mistake here
board[j].push([]);
}
}
}
function checkSquare(x, y){
if (typeof(board[x][y]) === ""){
return false;
} else {
return true;
}
}
initBoard();
console.log(checkSquare(3, 3));
var board = [];
function initBoard(){
for (var i = 0; i < 8; i++){
board.push([]);
for (var j = 0 ;j< i; j++){
board[j].push([]);
}
}
}
function checkSquare(x, y){
if (typeof(board[x][y]) === ""){
return false;
} else {
return true;
}
}
initBoard();
console.log(checkSquare(3, 3));
Two main things, you have a typo in your second loop, it should be based on j not i
and when you are trying to initialize the second array you can't use push because board[j] is undefined and push is a method of an array
var board = [];
function initBoard(){
for (var i = 0; i < 8; i++){
board.push([]);
for (var j = 0 ;j < 8; j++){
board[j] = [];
}
}
}
function checkSquare(x, y){
if (typeof(board[x][y]) === ""){
return false;
} else {
return true;
}
}
initBoard();
console.log(checkSquare(3, 3));
As the title, if the input is [[1,2], [3,4], [1,3], [5,6], [6,5]], output should be [[1,2,3,4], [5,6]].
It's wrong on the recursive part. In my code, after running it, I will get [[1,2,3],[1,3,4],[5,6]], which means I need once more merge, but I'm confused how to continue the code until no sub-array contains common element.
Here is my code
function need_merge_or_not(arr)
{
for (var i = 0; i <= arr.length-1; i++) {
for (var j = i+1; j <= arr.length-1; j++) {
var arr_new = arr[i].concat(arr[j]);
//remove deplicates
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
return true;
}
}
}
return false;
}
function merge(arr)
{
if (arr.length >= 2) {
for (var i = 0; i <= arr.length-1; i++) {
for (var j = i+1; j <= arr.length-1; j++) {
var arr_new = arr[i].concat(arr[j]);
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
arr.splice(arr.indexOf(arr[i]), 1);
arr.splice(arr.indexOf(arr[j]),1);
arr.push(arr_merge);
}
}
if (need_merge_or_not(arr)) {
return merge(arr);
}
}
}
return arr;
}
I figured it out. Here is the code:
function merge(arr){
var input = [];
for(var i = 0; i < arr.length; i++){
input.push(arr[i]);
}
if (arr.length >= 2) {
for (var i = 0; i < arr.length; i++) {
for (var j = i+1; j < arr.length; j++) {
var arr_new = arr[i].concat(arr[j]);
//remove duplicates
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
arr.splice(arr.indexOf(arr[i]), 1, arr_merge);
arr.splice(arr.indexOf(arr[j]),1);
j--;
}
}
}
if (!arraysEqual(input, arr)) {merge(arr)};
}
return arr;
//Input:[[1,2], [3,4], [1,3], [5,6], [6,5]]
//Output:[[1,2,3,4], [5,6]]
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
You could use two hash tables, one for the items and their groups and on for the result sets.
Basically the algorithm generates for the same group an object with a property and an array, because it allowes to keep the object reference while assigning a new array.
The main part is iterating the outer array and then the inner arrays and check inside, if it is the first item, then check the hash table for existence and if not exists, generate a new object with a values property and an empty array as value. Also assign the actual object to sets with item as key.
In a next step, the hash table is checked again and if not exist, then assign the object of the first element.
To maintain only unique values, a check is made and if the item does not exist, the item is pushed to the hash table's values array.
Then a part to join arrays follows by checking if the object of the first item is not equal to object of the actual item. If so, it delete from sets the key from the actual items's values first item and concat the array of the actual items to the first item's object's values. Then the values object is assigned to the actual item's object.
Later the sets are maped to the result set with iterating the sets object and the values property is taken as value.
var array = [[1, 2], [3, 4], [1, 3], [5, 6], [6, 5]],
groups = {},
sets = {},
result;
array.forEach(function (a) {
a.forEach(function (b, i, bb) {
if (i === 0 && !groups[b]) {
groups[b] = { values: [] };
sets[b] = groups[b];
}
if (!groups[b]) {
groups[b] = groups[bb[0]];
}
if (groups[b].values.indexOf(b) === -1) {
groups[b].values.push(b);
}
if (groups[bb[0]] !== groups[b]) {
delete sets[groups[b].values[0]];
groups[bb[0]].values = groups[bb[0]].values.concat(groups[b].values);
groups[b].values = groups[bb[0]].values;
}
});
});
result = Object.keys(sets).map(function (k) {
return sets[k].values;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
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));
I have an javascript array and I want to delete an element based on the value of the array, this is my array and this is what I have tried without success.
array = []
array.push (["Mozilla","Firefox",1.10])
index = array.indexOf(["Mozilla","Firefox",1.10])
array.splice(index, 1)
But it doesn't work, any idea¿?
You're trying to compare arrays, which are objects and have unique addresses. Your index variable is -1.
Try ['Mozilla','Firefox',1.10] === ['Mozilla','Firefox',1.10] in your console, you'll see that just because two arrays have the same values, it doesn't mean they are the same array.
What you need is a deep-equals style of comparison, that checks each value in the array, to see if two arrays have a likeness.
Take a look at lodash's isEqual function for an idea.
Here's a simple looping function:
function deepIndex(array, comparison) {
var i, j;
main:
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
for (j = 0; j < array[i].length; j++) {
if (array[i][j] !== comparison[j]) {
continue main;
}
}
return i;
}
}
}
var arr = [];
arr.push('string', ['Mozilla','Firefox',1.10], 'thing');
var index = deepIndex(arr, ['Mozilla','Firefox',1.10])
console.log(index, arr);
arr.splice(index, 1);
console.log(arr);
Take a look at this:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
This is function, made by the Creator of JQUery.
Basically you take the Index of one thing and than it is getting removed
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
//Equals Function taken from:
//http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
Array.prototype.equals = 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, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(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;
}
array = [];
array.push (["Mozilla","Firefox",1.10]);
array.push (["Microsoft","Spartan",1.0]);
array.push (["Safari","Safari",1.4]);
index = indexOfArr(array,["Mozilla","Firefox",1.10]);
array.remove(index, index);
document.getElementById("length").innerHTML = array.length;
for(var i = 0; i < array.length; i++){
document.getElementById("elems").innerHTML += "<br>"+array[i];
}
function indexOfArr(hay, needle){
for(var i = 0; i < hay.length; i++){
if (hay[i].equals(needle)){
return i;
}
}
return -1;
}
<span id = "length"></span><br>
<span id = "elems">Elements:</span>
You can use the fiter metodh, instead of indexOf.
Within the callback of that method, you can choose different approaches:
Use toString on the arrays and compare the two strings
Test for the length and the content, by iterating over the contained elements
... Continue ...
In any case using === will solve the problem, unless the object contained is exactly the same against which you are trying to match.
By the same, I mean the same. We are non speaking about having the same content, but to be the same instance.
Loop over your array and check the equality:
array = [];
array.push(["Mozilla", "Firefox", 1.10]);
for (var i = 0; i < array.length; i++) {
if (arraysEqual(array[i], ["Mozilla", "Firefox", 1.10])) {
array.splice(i, 1);
}
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
JSFiddle: http://jsfiddle.net/ghorg12110/r67jts35/
Based on this question : How to check if two arrays are equal with JavaScript?
You can do something like this
array = []
array.push (["Mozilla","Firefox",1.10])
tempArray = array[0];
index = tempArray.indexOf("Mozilla","Firefox",1.10)
array.splice(index, 1)
You can build on this if you put for loop instead of hard coding.
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;
}
});
});
}