问题
I have a 2d array like this:
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
Each index stores an inner array containing the coordinates of some element.
How can I use Array.indexOf() to check if the newly generated set of coordinates is already contained in arr? I want to push into arr if only the coordinate is NOT a duplicate.
Here is my attempt that didn\'t work:
if (arr.indexOf([x, y]) == -1) {
arr.push([x, y]);
}
It looks like indexOf() doesn\'t work for 2d arrays...
回答1:
You cannot use indexOf to do complicated arrays (unless you serialize it making everything each coordinate into strings), you will need to use a for loop (or while) to search for that coordinate in that array assuming you know the format of the array (in this case it is 2d).
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
var coor1 = [0, 9];
var coor2 = [1, 2];
function isItemInArray(array, item) {
for (var i = 0; i < array.length; i++) {
// This if statement depends on the format of your array
if (array[i][0] == item[0] && array[i][1] == item[1]) {
return true; // Found it
}
}
return false; // Not found
}
// Test coor1
console.log("Is it in there? [0, 9]", isItemInArray(arr, coor1)); // True
// Test coor2
console.log("Is it in there? [1, 2]", isItemInArray(arr, coor2)); // False
// Then
if (!isItemInArray(arr, [x, y])) {
arr.push([x, y]);
}
This implementation loops and grabs every value. If you care about performance you can do more complicated things like sorting the original array by the first index and then using binary search on the first index.
Another way is to bucket the first coordinate of each item in the array in an object (like a hashtable) and bucket the second value in each of those buckets to reduce search times; more info here http://en.wikipedia.org/wiki/Bucket_sort.
Otherwise this is probably good enough for what you need.
回答2:
Working js fiddle
for(var k = 0; k < arr.length; k++){
if(arr[k][0] == x && arr[k][1] == y){
found = true;
}
}
Much more of a hacky way than a simple index of, but it works
回答3:
Not a complete answer just a side note that may help.
Use Lodash
This method will get you the position of a value within a 2 dimensional array
let a = [ [ 'bird' ], [ 'cat' ], [ 'dog' ], [ 'cow' ], [ 'bird' ] ];
let b = _.findIndex(a, function(el) { return el[0] == 'cow'; });
console.log(b);//answer is 3
As mentioned earlier you need a nested loop for traversing through the array.
回答4:
Because this is a two dimensional Array, you will need a nested for loop.
var newArr = [1, 2],
counter;
for ( var i = 0; i < arr.length; i++ ) {
for ( var x = 0; x = arr[i].length; x++ ) {
if ( arr[i][x] === newArr[x] {
counter++
}
if (counter === 2) {
alert('new coord!')
}
}
//reset counter
counter = 0;
}
回答5:
Very simple without indexOf...
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
const isDup = (x,y) => {
arr.find(it => JSON.stringify(it) == JSON.stringify([x,y])) == undefined ? arr.push([x,y]) : null
}
console.log(isDup(2,3)) /* Does not add */
console.log(isDup(1,2)) /*Does add*/
console.log(arr) /*Confirmation*/
回答6:
Here is a solution done using prototype so the usage resembles that of indexOf but for 2d arrays. Use in the same way: arr.indexOf2d([2,3]);
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
Array.prototype.indexOf2d = function(item) {
// arrCoords is an array with previous coordinates converted to strings in format "x|y"
arrCoords = JSON.stringify(this.map(function(a){return a[0] + "|" + a[1]}));
// now use indexOf to find item converted to a string in format "x|y"
return arrCoords.indexOf(item[0] + "|" + item[1]) !== -1;
}
arr.indexOf2d([2,3]); // true
arr.indexOf2d([1,1]); // true
arr.indexOf2d([6,1]); // false
回答7:
A previous answer said:
You cannot use indexOf to do complicated arrays (unless you serialize it making everything each coordinate into strings)...
Here's how you'd do just that. If you have an extremely large data set, I'd recommend against this technique, as it relies on a duplicate of your 2D array. But for reasonable sets, it's simple.
Use a consistent method for flattening array elements, such as:
// Flatten array into a string, separating elements with a "unique" separator.
function stringle( arr ) {
return arr.join(' |-| ');
}
This is overkill for your example, where sub-arrays contain integers, but it accounts for more complex data types. (If we used a comma, the default, it would be indiscernible from a string element that contained a comma, for example.)
Then the target array can be flattened into an array of strings:
// Transmogrify arr into a String[], usable with indexOf()
var arrSearch = arr.map(function(row) { return stringle(row); });
Then you can use Array.indexOf() (or other array methods) to check for the presence or location of matches.
if (arrSearch.indexOf( stringle(newArray) ) === -1) ...
This snippet contains a demo of this, with multiple data types.
// Example starting array
var arr = [[2,3],[5,8],[1,1],[0,9],[5,7]];
// Flatten array into a string, separating elements with a "unique" separator.
function stringle( arr ) {
return arr.join(' |-| ');
}
snippet.log("arr: "+JSON.stringify(arr));
// Transmogrify arr into a String[], usable with indexOf()
var arrSearch = arr.map(function(row) { return stringle(row); });
snippet.log("arrSearch: "+JSON.stringify(arrSearch));
var tests = [[0, 9],[1, 2],["pig","cow"],[0,9,"unicorn"],["pig","cow"]];
for (var test in tests) {
var str = stringle(tests[test]);
if (arrSearch.indexOf(str) === -1) {
arr.push(tests[test]);
arrSearch.push(str);
snippet.log("Added "+JSON.stringify(tests[test]));
}
else {
snippet.log("Already had "+JSON.stringify(tests[test]));
}
}
snippet.log("Result: "+JSON.stringify(arr));
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
回答8:
you can use this method,
function isArrayItemExists(array , item) {
for ( var i = 0; i < array.length; i++ ) {
if(JSON.stringify(array[i]) == JSON.stringify(item)){
return true;
}
}
return false;
}
来源:https://stackoverflow.com/questions/24943200/javascript-2d-array-indexof