i have an 2-dimensional array. for example
var bruecken = [[1,2],[3,4]];
now i am trying to test, if a subarray exists:
console.log(jQuery.inArray([1,2], bruecken));
or
console.log(bruecken.indexOf([1,2]));
but both ways it returns -1. what am i doing wrong?
The fastest way would be to use a for loop and compare them, then return if found. Here is something you can work with, I used JSON for comparison, but you can just use whatever comparator you find best (there are plenty):
function arrayInArray(needle, haystack) {
var i=0, len=haystack.length, target=JSON.stringify(needle);
for(; i<len; i++) {
if (JSON.stringify(haystack[i]) == target) {
return i;
}
}
return -1;
}
arrayInArray( [0,1], [ [1,2], [0,1] ] ); // 1
If you want booleans, just return true instead of i and false instead of -1.
I don't think inArray will work because comparing two identical arrays using == will return false. You could try using grep instead:
function subArrayInArray(subArray, array){
var matches = $.grep(array, function(a){
// Compare the target array with each of the child arrays
return $(subArray).not(a).length == 0 && $(a).not(subArray).length == 0;
});
return !!matches.length;
}
The method for comparing two arrays was stolen from this question
Related
I was doing a little coding challenge, and it was to write a function that would return true if the arr parameter, which was an array of number, was sorted in ascending order. I can't seem to figure this out, but my code, no matter what, always returns true.
function inAscOrder(arr) {
return arr.sort() === arr;
}
As others have pointed out, a major issue with your version is that it uses the mutating sort. Although you could fix this by inserting a slice(0) or some such to clone the array, and then writing an index-by-index equality tester, it's much easier to simply test if each successive entry is larger than the previous one.
Perhaps the most elegant way to do that is through recursion. Here's one example:
const inAscOrder = (a) => a.length < 2 || (a[0] < a[1] && inAscOrder(a.slice(1)))
This might not be workable for larger arrays because of Javascript's recursion depth limits. But an iterative version of the same thing is fairly straightforward:
const inAscOrder = (a) => {
if (a.length < 2) {return true}
for (let i = 1; i < a.length; i++) {
if (a[i -1] > a[i]) {return false}
}
return true
}
You do not need to sort the array to see if it is sorted. Just you need to check whether it is sorted or not.
static boolean arraySortedOrNot(int arr[], int n)
{
// Array has one or no element
if (n == 0 || n == 1)
return true;
for (int i = 1; i < n; i++)
// Unsorted pair found
if (arr[i-1] > arr[i])
return false;
// No unsorted pair found
return true;
}
reference link:
https://www.geeksforgeeks.org/program-check-array-sorted-not-iterative-recursive/
Since array is a mutable datatype, your arr will get modified when you call the sort method on it.
So arr.sort() will modify your array instead of just returning a sorted array. So thats why when u check again if its equal to arr, it will be the same sorted array.
To overcome this I suggest you copy the arr to some another array and sort that and test it.
Here is a simple example of an array that contains at least one other array. I want a way to find the index of an array, within an array. However, the code I have below does not work:
var arr = [1,2,[1,2]];
console.log(arr.indexOf([1,2])); //-> -1
for (var i = 0; i < arr.length; i++) {
if (arr[i] == [1,2])
return 'true' // does not return true
}
Intuitively, this should work but does not:
if ([1,2] == [1,2]) return 'true' // does not return true
Can someone explain why it does not work, and offer an alternative solution? Thanks!
No, but you can check it yourself:
var a = [1,2], b = [1,2];
a.length === b.length && a.every(function(x,y) { return x === b[y]; });
Arrays in JavaScript are compared by reference not by value. That is why
console.log([1,2] == [1,2])
returns false.
You need a custom function that could compare arrays. If you want to check only the first level of nesting you can use this code:
var compareArrays = function(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
You are confusing the definitions of similar objects vs. the same object. Array.prototype.indexOf() compares the objects using the strict equality comparison algorithm. For (many) objects, this means an object reference comparison (i.e. the object's unique identifier, almost like its memory address).
In your example above, you are trying to treat two similar arrays as though they were the same array, and that's why it doesn't work. To do what you are trying to do, you need to use the same array. Like this:
var testArr = [1,2]; //a specific object with a specific reference
var arr = [1,2,testArr]; //the same array, not a different but similar array
console.log(arr.indexOf(testArr)); //returns 2
If you just want to know where arrays occur in the parent array, use Array.isArray():
...
if(Array.isArray(arr[i])) {
//do something
}
...
Hopefully that helps!
I have a 2d array similar to this:
var array = [
{100,200},
{200,200},
{100,400}
];
Now I want to find if a known array exists inside the 2d array. For example, I want to check if [200,200] exists as a 2nd level array inside the 2d array.
On 1d arrays in the past I've used something like:
if (value in array) {...}
Can't seem to get that method working on 2d. What is the best solution?
Not sure if you already know but your syntax is not correct. It should look like this:
var array = [
[100,200],
[200,200],
[100,400]
];
A naive way to check if [200, 200] exists as a 2nd level array:
console.log(array[1][0] == 200 && array[1][1] == 200);
Another naive approach is to use a nested loop and go through each item.
If you want a fast approach to this, you might want to read up on search algorithms.
Searching Algorithms
var array = [
[100,200],
[200,200],
[100,400]
];
var searchFor = [200,200];
function arrayExistsInside(haystack, needle) {
for(var i = 0; i < haystack.length; i++) {
if(compareArray(haystack[i], needle)) return true;
}
return false;
}
function compareArray(array1, array2) {
if(array1.length != array2.length) return false;
for(var i = 0; i < array1.length; i++) {
if(array1[i] != array2[i]) return false;
}
return true;
}
if(arrayExistsInside(array, searchFor)) { ... }
You could also use the compare function outlined on How to compare arrays in JavaScript?
I found a solution to where I get returned an array of elements without duplicates:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) == -1;
});
However, I want to modify this code just a little bit. Instead of being returned an array without duplicates, I want to do something when there is a duplicate. The problem is, I'm not sure how exactly this code works. The thing is I'm not sure how val gets set, or what it even is.
for (var i = 0; i < json.length; i++) {
var item = json[i];
// if json.indexOf(val?), do something
}
Read the docs for the Array filter method then. The val parameter of the callback will be passed the single array items, i.e. json[i] or item in your case:
for (var i = 0; i < json.length; i++) {
var item = json[i];
if (json.indexOf(item) >= 0) {
// do something
}
}
var newArray = array1.filter(function(v, i) {
return array1.indexOf(v) == i;
});
This will return only unique itesm from array1;
array1.filter(function(v, i) {
// write your code here ('v' is individual value and 'i' is its index)
// don't return any anything if you don't want unique array to be returned.
// 'array1.indexOf(v) == i' checks if current value is duplicate from previous any values.
// try putting console.log on values you don't understand like (console.log(v,i) for values of 'v' and 'i')
return array1.indexOf(v) == i;
});
and off-curse you can loop an array with for loop as
for(i in array1){
// where i is index of array1, to get current value use array1[i]
if(array2.indexOf(array1[i]) >= 0){
// do something
}
console.log(i);
}
val is set by Array.prototype.filter, which calls the callback function on each element in the array. Since you don't want to filter you can use Array.prototype.forEach instead, which also calls the callback function once for each element in the array:
Array1.forEach(
// This function is called once per element in Array1
function(val){
if(Array2.indexOf(val) != -1){ // Check if that element is also in Array2
// `val` is in both arrays,
// Do something with it
}
}
);
You can utilize some modern libraries... like underscorejs.
Intersection is what you're looking for i guess: http://underscorejs.org/#intersection
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
So your code may be something like
if(_.insersection(arr1, arr2)){
//since [] array is Falsy in JS this will work as a charm
}
From MDN: indexOf
Returns the first index at which a given element can be found in the array, or -1 if it is not present.
From MDN: filter
Creates a new array with all elements that pass the test implemented by the provided function.
The first function works by returning true when an item from array1 isn't found in array2 (== -1). i.e.: Iterate through A and add anything not found in B.
So, to change to return only duplicates return true for anything that is found in both:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) >= 0;
});
Array1 now contains only items with duplicates.
I have a little piece of code where an array is populated with arrays. At the end, I have this array with n member arrays. These sub-arrays always have the same number of members (2) of the same type (number). I need to know if these sub-arrays are all identical (same members, same position). This always returns false:
[2, 0] === [2, 0]
Off the top of my head, I can think of two ways to compare.
A loop in which I test (member[i][0] === member[i+1][0] && member[i][1] === member[i+1][1]).
The same loop, with this test: (member[i].toString() === member[i + 1].toString()).
I think I'm taking this the wrong way. What do you think?
FOR MY OWN THINKING, I think it is correct to use the loop to compare two array.
var isTheSame = true;
for (var i in array1) {
if (array1[i] !== array2[i]) isTheSame = false;
}
The loop above works, it will return false either any of the element different from type (three equal sign ===), or value, or length or even key.
The second suggestion of you should not work as exactly as the first one, because you convert it into a string already, what happen if array1[0] = "true" and array2[0] = true? It will return true, because now all of them are string, but you need the exact comparison right?
That's my own thinking, I hope it might help somehow.
Regards,
[x]
a=[2,0]; b=[2,0]; a.toString() == b.toString();
perhaps not the most efficient, but it seems to work, and I'm a strong proponent of the shorter and more readable solution.
note that xx3004's point about the type data lost when converting to string is something to think about, unless you know for sure that your arrays will be composed of the same data types.
You can use the below to get true or false on whether two one-dimensional arrays are identical. It needs to be recursive if you add dimensions, but this will suffice for what you're asking, I think.
function testArray(a, b) {
var aLen = a.length;
var bLen = b.length;
if (aLen === bLen) { // check for identical length first
for (var i = 0; i < aLen; i++) {
if (a[i] !== b[i]) {
return false; // members don't match
}
}
return true; // all members matched
}
return false; // not same length
}
http://jsfiddle.net/pgkUr/
This is what I came up with...
var arrayCompare = function(a, b) {
var aLength = a.length,
bLength = b.length;
if (aLength != bLength) {
return false;
}
for (var i = 0; i < aLength; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
Here's an easy way to compare the two arrays, building on your toString idea (even multidimensional ones will work):
function compareArrays(a1, a2) {
return JSON.stringify(a1) == JSON.stringify(a2);
}
compareArrays([[2,3],[7,4],[3,3]], [[2,3],[7,4],[3,3]]) // true
compareArrays([[2,3],[7,4],[3,3]], [[7,4],[2,3],[3,3]]) // false
If your willing to use Underscore, which is simply great tool (I value it as much or even higher than jQuery), you could simplify this code quite a lot. You don't need nesting during comparing arrays: I would flatten them beforehand. Then it's just one loop:
function cmpArrays( arr1, arr2 ){
var flat = _.zip( _.flatten( arr1 ), _.flatten( arr2 ) );
for( var elem in flat ){
if( flat[elem][0] !== flat[elem][1] ){
return false;
}
}
return true;
}
generalizing this to work with any number of arrays should be very simple as well.