web-dev-qa-db-fra.com

Jquery comment trouver un objet par attribut dans un tableau

Étant donné que j'ai un tableau d'objets "but":

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

(pour simplifier, j'omets d'autres attributs)

Maintenant, je veux une méthode qui retourne un objet spécifique si un nom d'objet correspondant est trouvé.

Cela ne fonctionne pas:

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

findPurpose("daily");

mais elle renvoie en réalité un tableau vide:

[]

J'utilise JQuery 1.5.2. J'ai aussi essayé avec $ .each () mais sans succès. Apparemment, la plupart des méthodes JQuery sont conçues pour être utilisées avec des éléments DOM (tels que filter().

Des idées sur la façon de réaliser ceci?

62

L'erreur était que vous ne pouvez pas utiliser this dans le grep, mais vous devez utiliser une référence à l'élément. Cela marche:

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

findPurpose("daily");

résultats:

[Object { purpose="daily"}]
26

ES6

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

En savoir plus sur la méthode findici .

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
}

Remarque

jQuery $ .grep (ou une autre fonction de filtrage) n'est pas la solution optimale.

Le $.grep fonction fonctionnera en boucle sur tous les éléments du tableau, même si l’objet recherché a déjà été trouvé au cours de la boucle. À partir de la documentation jQuery grep:

La méthode $ .grep () supprime les éléments d'un tableau si nécessaire pour que tous les éléments restants passent un test fourni. Le test est une fonction à laquelle sont attribués un élément de tableau et l'index de l'élément dans le tableau. Ce n'est que si le test renvoie vrai que l'élément sera dans le tableau de résultats.

78
Luca Fagioli

vous devriez passer la référence à item dans la fonction grep:

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

Exemple

37
Andrei

Personnellement, j'utilise une fonction plus générique qui fonctionne pour n'importe quelle propriété d'un tableau:

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];
}

Vous appelez ça comme ça:

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

Utilisez la fonction Underscore.js findWhere ( http://underscorejs.org/#findWhere ):

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

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

daily serait égal à:

{"purpose":"daily"}

Voici un violon: http://jsfiddle.net/spencerw/oqbgc21x/

Pour retourner plus d'un ( si vous en avez plus dans votre tableau), vous pouvez utiliser _.where(...)

5
jbobbins

Le meilleur, le plus rapide est

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

Si votre tableau est en réalité un ensemble d’objets JQuery, pourquoi ne pas utiliser simplement la méthode . Filter () ?

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

Une autre solution:

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

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

Cette fonction ne s'exécute pas pour chaque élément du tableau (utile pour les grands tableaux).

1
feeeper

Javascript a juste une fonction pour cela: Array.prototype.find . Comme exemple

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

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

Il n'est pas difficile d'étendre le rappel à une fonction. Cependant, ceci n'est pas compatible avec IE (et partiellement avec Edge). Pour une liste complète, consultez le Compatibilité du navigateur

0
user2688838

J'ai créé un service util pour mon application angular. Elle a deux fonctions qui utilisent très souvent.

Par exemple, vous avez un objet.

Obtenir d'abord la valeur de l'objet de manière récursive sans générer d'erreur non définie.

{prop: {nestedProp1: {nestedProp2: somevalue}}}; Obtenez nestedProp2 2 sans contrôles non définis.

Deuxième filtre sur base

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

Rechercher un objet dans un tableau avec 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;
}});

Pour solution à la question actuelle. injecter UtilService et appeler,

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

Ou plus avancé

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

copié à partir du code polyfill Array.prototype.find de Array.find et ajouté le tableau en tant que premier paramètre.

vous pouvez passer le terme de recherche comme fonction de prédicat

// 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