web-dev-qa-db-ja.com

jquery配列の属性でオブジェクトを見つける方法

「目的」オブジェクトの配列がある場合:

_//array of purpose objects:
var purposeObjects = [
    {purpose: "daily"},
    {purpose: "weekly"},
    {purpose: "monthly"}
];
_

(簡単にするため、他の属性は省略しています)

一致する目的名が見つかった場合、オブジェクトの特定の1つを返すメソッドが必要になりました。

これは機能していません:

_function findPurpose(purposeName){
    return $.grep(purposeObjects, function(){
      return this.purpose == purposeName;
    });
};

findPurpose("daily");
_

しかし、実際には空の配列を返します。

_[]
_

JQuery 1.5.2を使用しています。私も$ .each()を試しましたが、運はありません。明らかに、ほとんどのJQueryメソッドは、DOM要素(filter()など)で使用するために設計されています。

これを達成する方法についてのアイデアはありますか?

62

エラーは、grepでthisを使用できないことですが、要素への参照を使用する必要がありました。これは動作します:

function findPurpose(purposeName){
    return $.grep(purposeObjects, function(n, i){
      return n.purpose == purposeName;
    });
};

findPurpose("daily");

返却値:

[Object { purpose="daily"}]
26

ES6

    array.find((o) => { return o[propertyName] === propertyValue })

findメソッドの詳細 here

ES5

var findPurpose = function(purposeName) {
    for (var i = 0, len = purposeObjects.length; i < len; i++) {
        if (purposeObjects[i].purpose === purposeName)
            return purposeObjects[i]; // Return as soon as the object is found
    }
    return null; // The object was not found
}

注意

jQuery $ .grep(または他のフィルタリング関数)は最適なソリューションではありません。

$.grep関数は、ループ中に検索されたオブジェクトがすでに見つかった場合でも、配列の要素をallループスルーします。 jQuery grepドキュメントから:

$ .grep()メソッドは、必要に応じて配列から項目を削除し、残りのすべての項目が提供されたテストに合格するようにします。テストは、配列アイテムと配列内のアイテムのインデックスを渡す関数です。テストがtrueを返した場合のみ、アイテムは結果配列になります。

78
Luca Fagioli

grep関数でアイテムの参照を渡す必要があります。

function findPurpose(purposeName){
    return $.grep(purposeObjects, function(item){
      return item.purpose == purposeName;
    });
};

37
Andrei

私は個人的に、任意の配列の任意のプロパティに対して機能するより一般的な関数を使用します。

function lookup(array, prop, value) {
    for (var i = 0, len = array.length; i < len; i++)
        if (array[i] && array[i][prop] === value) return array[i];
}

次のように呼び出すだけです。

lookup(purposeObjects, "purpose", "daily");
29
Johann

Underscore.jsのfindWhere関数を使用します( http://underscorejs.org/#findWhere ):

_var purposeObjects = [
    {purpose: "daily"},
    {purpose: "weekly"},
    {purpose: "monthly"}
];

var daily = _.findWhere(purposeObjects, {purpose: 'daily'});
_

dailyは次のようになります。

_{"purpose":"daily"}
_

ここにフィドルがあります: http://jsfiddle.net/spencerw/oqbgc21x/

複数を返すには(if配列に複数ある場合)_.where(...)を使用できます

5
jbobbins

最高の、最速の方法は

function arrayLookup(array, prop, val) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].hasOwnProperty(prop) && array[i][prop] === val) {
            return array[i];
        }
    }
    return null;
}
4
Kalim

配列が実際にJQueryオブジェクトのセットである場合、単純に 。filter() メソッドを使用するのはどうですか?

purposeObjects.filter('[purpose="daily"]')
3
Douglas

もう1つのソリューション:

_function firstOrNull(array, expr) {
  for (var i = 0; i < array.length; i++) {
    if (expr(array[i]))
      return array[i];
    }
  return null;
}
_

使用:firstOrNull([{ a: 1, b: 2 }, { a: 3, b: 3 }], function(item) { return item.a === 3; });

この関数は、配列の各要素に対して実行されません(大きな配列の場合に役立ちます)

1
feeeper

Javascriptには、そのための関数 Array.prototype.find があります。例として

function isBigEnough(element) {
  return element >= 15;
}

[12, 5, 8, 130, 44].find(isBigEnough); // 130

コールバックを関数に拡張することは難しくありません。ただし、これはIE(および部分的にEdge)と互換性がありません。完全なリストについては、 ブラウザ互換性

0
user2688838

angularアプリケーションにutilサービスを作成しました。非常に頻繁に使用する2つの関数があります。

たとえば、オブジェクトがあります。

未定義のエラーをスローすることなく、最初にオブジェクトから値を再帰的に取得します。

{prop:{nestedProp1:{nestedProp2:somevalue}}};未定義のチェックなしでnestedProp2 2を取得します。

ベースの2番目のフィルター配列

[{prop:{nestedProp1:{nestedProp2:somevalue1}}}、{prop:{nestedProp1:{nestedProp2:somevalue2}}}];

NestedProp2 = somevalue2を使用して配列からオブジェクトを検索します

app.service('UtilService', function(httpService) {
this.mapStringKeyVal = function(map, field) {
    var lastIdentifiedVal = null;
    var parentVal = map;
    field.split('.').forEach(function(val){
        if(parentVal[val]){
            lastIdentifiedVal = parentVal[val]; 
            parentVal = parentVal[val]; 
        }
    });
    return lastIdentifiedVal;
}


this.arrayPropFilter = function(array, field,value) {
    var lastIdentifiedVal = null;
    var mapStringKeyVal = this.mapStringKeyVal;
    array.forEach(function(arrayItem){
        var valueFound = mapStringKeyVal(arrayItem,field);
        if(!lastIdentifiedVal  && valueFound && valueFound==value){
            lastIdentifiedVal = arrayItem;
        }
    });
    return lastIdentifiedVal;
}});

現在の質問の解決策。 UtilServiceを注入して呼び出し、

UtilService.arrayPropFilter(purposeArray,'purpose','daily');

またはより高度な

UtilService.arrayPropFilter(purposeArray,'purpose.nestedProp1.nestedProp2','daily');
0
sanjay patel

array.findのpolyfill Array.prototype.findコードからコピーし、最初のパラメーターとして配列を追加しました。

検索語を述語関数として渡すことができます

// Example
var listOfObjects = [{key: "1", value: "one"}, {key: "2", value: "two"}]
var result = findInArray(listOfObjects, function(element) {
  return element.key == "1";
});
console.log(result);

// the function you want
function findInArray(listOfObjects, predicate) {
      if (listOfObjects == null) {
        throw new TypeError('listOfObjects is null or not defined');
      }

      var o = Object(listOfObjects);

      var len = o.length >>> 0;

      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }

      var thisArg = arguments[1];

      var k = 0;

      while (k < len) {
        var kValue = o[k];
        if (predicate.call(thisArg, kValue, k, o)) {
          return kValue;
        }
        k++;
      }

      return undefined;
}
0
Abou-Emish