52

オブジェクトを含む配列があります。

このようなもの:

var arr = new Array(
  {x:1, y:2},
  {x:3, y:4}
);

私がしようとすると:

arr.indexOf({x:1, y:2});

返します-1

文字列、数値、またはオブジェクト以外の他のタイプの要素がある場合は、正常にindexOf()機能します。

配列内のオブジェクト要素を検索する理由と何をすべきかを誰かが知っていますか?

もちろん、オブジェクトの文字列ハッシュキーを作成して配列に渡す以外の方法を意味します...

4

8 に答える 8

47

indexOf は、厳密な等価性を使用して searchElement を Array の要素と比較します (=== またはトリプルイコール演算子で使用されるのと同じ方法)。

===オブジェクトの等価性のチェックには使用できません。

@RobG指摘したように

定義上、2 つのオブジェクトがまったく同じプロパティ名と値を持っていても、決して等しくないことに注意してください。objectA === objectBobjectA と objectB が同じオブジェクトを参照している場合に限ります。

カスタム indexOf 関数を記述して、オブジェクトをチェックするだけです。

function myIndexOf(o) {    
    for (var i = 0; i < arr.length; i++) {
        if (arr[i].x == o.x && arr[i].y == o.y) {
            return i;
        }
    }
    return -1;
}

デモ: http://jsfiddle.net/zQtML/

于 2012-09-26T14:33:43.343 に答える
12

前述のように、2 つのオブジェクトが等しくなることはありませんが、参照が同じオブジェクトに対するものである場合、参照は等しくなる可能性があるため、コードで目的の処理を行うには、次のようにします。

var a = {x:1, y:2};
var b = {x:3, y:4};
var arr = [a, b];

alert(arr.indexOf(a)); // 0

編集

これは、より一般的なspecialIndexOf関数です。オブジェクトの値がプリミティブであることを期待していることに注意してください。それ以外の場合は、より厳密にする必要があります。

function specialIndexOf(arr, value) {
  var a;
  for (var i=0, iLen=arr.length; i<iLen; i++) {
    a = arr[i];

    if (a === value) return i;

    if (typeof a == 'object') {
      if (compareObj(arr[i], value)) {
        return i;
      }
    } else {
      // deal with other types
    }
  }
  return -1;

  // Extremely simple function, expects the values of all 
  // enumerable properties of both objects to be primitives.
  function compareObj(o1, o2, cease) {
    var p;

    if (typeof o1 == 'object' && typeof o2 == 'object') {

      for (p in o1) {
        if (o1[p] != o2[p]) return false; 
      }

      if (cease !== true) {
        compareObj(o2, o1, true);
      }

      return true;
    }
  }
}

var a = new String('fred');
var b = new String('fred');

var arr = [0,1,a];

alert(specialIndexOf(arr, b)); // 2
于 2012-09-26T14:43:24.107 に答える
11

これはカスタムコードなしで機能します

var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true

注:これは実際のインデックスを提供するものではなく、オブジェクトが現在のデータ構造に存在するかどうかのみを示します

于 2015-08-01T03:08:42.767 に答える
3

それらのオブジェクトは等しくありません。

独自の関数を実装する必要があります。

あなたはそれを例えばするかもしれません:

var index = -1;
arr.forEach(function(v, i) {
   if (this.x==v.x && this.y==v.y) index=i;
}, searched); 

オブジェクトの1つはどこにsearchedありますか(またはそうではありません)。

(単純なループで実装しますが、foreachの方がきれいです)

于 2012-09-26T14:36:44.920 に答える
3

2 つの別個のオブジェクトは===互いに接していないため、 をindexOf使用します===。(彼らは==お互いにそうではありません。)

例:

var a = {x:1, y:2};
var b = {x:1, y:2};
console.log(a === b);

===オペランドが同等のオブジェクト (同じプロトタイプとプロパティを持つオブジェクト)を参照しているかどうかではなく、それらのオペランドが同じオブジェクトを参照しているかどうかを==テストします。

于 2016-10-07T20:57:35.943 に答える
0

比較関数をパラメーターとして渡す別のソリューションを次に示します。

function indexOf(array, val, from, compare) {

  if (!compare) {
    if (from instanceof Function) {
      compare = from;
      from = 0;
    }
    else return array.__origIndexOf(val, from);
  }

  if (!from) from = 0;

  for (var i=from ; i < array.length ; i++) {
    if (compare(array[i], val))
      return i;
  }
  return -1;
}

// Save original indexOf to keep the original behaviour
Array.prototype.__origIndexOf = Array.prototype.indexOf;

// Redefine the Array.indexOf to support a compare function.
Array.prototype.indexOf = function(val, from, compare) {
  return indexOf(this, val, from, compare);
}

その後、次のように使用できます。

indexOf(arr, {x:1, y:2}, function (a,b) {
 return a.x == b.x && a.y == b.y;
});

arr.indexOf({x:1, y:2}, function (a,b) {
 return a.x == b.x && a.y == b.y;
});

arr.indexOf({x:1, y:2}, 1, function (a,b) {
 return a.x == b.x && a.y == b.y;
});

良いことは、比較関数が渡されない場合でも、元の indexOf を呼び出すことです。

[1,2,3,4].indexOf(3);
于 2015-06-25T20:24:17.573 に答える
0

このタイプの回答に興味がないように見えますが、興味のある他の人のために作成するのが最も簡単です:

var arr = new Array(
    {x:1, y:2},
    {x:3, y:4}
);

arr.map(function(obj) {
    return objStr(obj);
}).indexOf(objStr({x:1, y:2}));

function objStr(obj) {
    return "(" + obj.x + ", " + obj.y + ")"
}
于 2016-05-25T18:45:18.433 に答える