Comment trouver une valeur dans un tableau d'objets en JavaScript?

90

J'ai un tableau d'objets:

Object = {
   1 : { name : bob , dinner : pizza },
   2 : { name : john , dinner : sushi },
   3 : { name : larry, dinner : hummus }
}

Je veux pouvoir rechercher dans l'objet / tableau où la clé est «dîner», et voir si cela correspond à «sushi».

Je sais que jQuery a $ .inArray, mais il ne semble pas fonctionner sur des tableaux d'objets. Ou peut-être que je me trompe. indexOf semble également ne fonctionner que sur un seul niveau de tableau.

N'y a-t-il pas de fonction ou de code existant pour cela?

Questionneur
la source
Cela a déjà été demandé. Vous devez écrire votre propre fonction ou utiliser une autre bibliothèque.
Felix Kling
1
Veuillez noter que Objectc'est réservé en Javascript, Objectest l'objet objet, c'est à dire la mère de tous les objets.
adamse
1
La question et la réponse acceptée ne sont pas liées aux tableaux multidimensionnels, mais plutôt au filtrage de tableaux à une dimension par les valeurs de propriété de ses éléments. => Ils n'ont pas résolu mon problème "trouver une valeur dans un tableau multidimensionnel".
Martin Schneider

Réponses:

211

Si vous avez un tableau tel que

var people = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

Vous pouvez utiliser la filterméthode d'un objet Array:

people.filter(function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]

Dans les nouvelles implémentations JavaScript, vous pouvez utiliser une expression de fonction:

people.filter(p => p.dinner == "sushi")
  // => [{ "name": "john", "dinner": "sushi" }]

Vous pouvez rechercher des personnes qui "dinner": "sushi"utilisent unmap

people.map(function (person) {
  if (person.dinner == "sushi") {
    return person
  } else {
    return null
  }
}); // => [null, { "name": "john", "dinner": "sushi" }, null]

ou un reduce

people.reduce(function (sushiPeople, person) {
  if (person.dinner == "sushi") {
    return sushiPeople.concat(person);
  } else {
    return sushiPeople
  }
}, []); // => [{ "name": "john", "dinner": "sushi" }]

Je suis sûr que vous êtes en mesure de généraliser cela à des clés et des valeurs arbitraires!

Adamse
la source
7
Gardez simplement à l'esprit que ces solutions font partie d'ECMAScript 5 et ne sont pas prises en charge dans IE8. kangax.github.com/es5-compat-table Autant que je préfère la réponse de @ adamse, alex est plus convivial pour les "vieux navigateurs de merde". Pas sûr de la performance cependant.
EasyCo
@SalmanA - ni la question ni la solution ne se réfèrent à jQuery. Le filtre javascript () est utilisé, pas spécifique à jQuery $ .filter () - tutorialspoint.com/javascript/array_filter.htm
Tapirboy
Comme mentionné par EasyCo, la fonction de filtrage n'est pas prise en charge dans IE8. Cependant, il est facilement ajouté au prototype Array et donc utilisable dans n'importe quel navigateur avec une petite fonction au début de vos scripts. Ceci est décrit dans la documentation du filtre . Il donne la fonction exacte spécifiée dans ECMA-262, donc c'est littéralement la même chose.
dallin
1
Je viens d'ajouter une réponse qui utilise la grepméthode de jQuery . Cela peut avoir du sens de passer à votre réponse car c'est le même concept que ce que vous faites, mais dépendant de jQuery et convivial pour les navigateurs de merde.
Zach Lysobey
Y a-t-il une raison pour laquelle je reçois toujours une erreur de référence avec ma variable de retour? J'ai essayé les deux premières réponses en retournant "x" et ça n'arrête pas de dire que c'est indéfini ...
Evan Lalo
18

jQuery a une méthode intégrée jQuery.grepqui fonctionne de manière similaire à la filterfonction ES5 de la réponse de @ adamse et devrait fonctionner correctement sur les navigateurs plus anciens.

En utilisant l'exemple d'Adamse:

var peoples = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

vous pouvez faire ce qui suit

jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]
Zach Lysobey
la source
10
var getKeyByDinner = function(obj, dinner) {
    var returnKey = -1;

    $.each(obj, function(key, info) {
        if (info.dinner == dinner) {
           returnKey = key;
           return false; 
        };   
    });

    return returnKey;       

}

jsFiddle .

Tant que ce -1n'est jamais une clé valide.

Alex
la source
presque voté pour celui-ci, mais il n'y avait aucune explication dans le message.
mickmackusa
10

Si vous allez effectuer cette recherche fréquemment, pensez à changer le format de votre objet afin que le dîner soit réellement une clé. C'est un peu comme l'attribution d'une clé de cluster primaire dans une table de base de données. Ainsi, par exemple:

Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }

Vous pouvez maintenant y accéder facilement comme ceci: Object['sushi']['name']

Ou si l'objet est vraiment aussi simple (juste 'nom' dans l'objet), vous pouvez simplement le changer en:

Obj = { 'pizza' : 'bob', 'sushi' : 'john' }

Et accéder ensuite comme: Object['sushi'].

Il n'est évidemment pas toujours possible ou à votre avantage de restructurer votre objet de données comme celui-ci, mais le fait est que la meilleure réponse est parfois de déterminer si votre objet de données est structuré de la meilleure façon. Créer une clé comme celle-ci peut être plus rapide et créer un code plus propre.

Dallas
la source
1
J'adore la réponse, mais j'ai trouvé un problème avec la syntaxe: le mien ne fonctionnait que comme ceci: obj = {"pizza": {"name": "bob"}, "sushi": {"name": "john"}} alert ( obj ['pizza'] ['nom']); mais reste. Merci! trouvé ce que je cherchais! )
aleXela
@alexela Merci alexela! J'ai mis à jour ma réponse avec votre observation astucieuse! Je venais de copier l'exemple dans le post de l'OP et j'avais négligé d'ajouter les guillemets, mais vous avez raison - cela ne fonctionnera pas à moins qu'il n'y ait au moins des guillemets autour des valeurs (en supposant que ce sont des valeurs et non des variables).
dallin
3

Vous pouvez trouver l'objet dans un tableau avec la bibliothèque Alasql :

var data = [ { name : "bob" , dinner : "pizza" }, { name : "john" , dinner : "sushi" },
     { name : "larry", dinner : "hummus" } ];

var res = alasql('SELECT * FROM ? WHERE dinner="sushi"',[data]);

Essayez cet exemple dans jsFiddle .

agershun
la source
3
Je ne suis pas sûr que cela méritait vraiment d'être voté contre. Les requêtes SQL sur les collections deviennent beaucoup plus faciles à raisonner et à écrire lorsque les exigences deviennent plus compliquées qu'un seul filtre ou réduisent les appels. Alasql est une bibliothèque assez impressionnante, mais certes un peu exagérée pour l'exemple ci-dessus.
TomDotTom
1
si l'objet lui-même provient d'une source SQL, alors cette réponse est un pur génie.
edwardsmarkf
1

Vous pouvez utiliser une simple boucle for in:

for (prop in Obj){
    if (Obj[prop]['dinner'] === 'sushi'){

        // Do stuff with found object. E.g. put it into an array:
        arrFoo.push(Obj[prop]);
    }
}

L'exemple de violon suivant place tous les objets qui contiennent dinner:sushidans un tableau:

https://jsfiddle.net/3asvkLn6/1/

Rotareti
la source
1

Il y a déjà beaucoup de bonnes réponses ici alors pourquoi pas une de plus, utilisez une bibliothèque comme lodash ou underscore :)

obj = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
}

_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]
TomDotTom
la source
0

J'ai dû rechercher une structure de plan de site imbriquée pour le premier élément feuille qui trace un chemin donné. Je suis venu avec le code suivant en utilisant simplement .map() .filter()et .reduce. Renvoie le dernier élément trouvé qui correspond au chemin /c.

var sitemap = {
  nodes: [
    {
      items: [{ path: "/a" }, { path: "/b" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    }
  ]
};

const item = sitemap.nodes
  .map(n => n.items.filter(i => i.path === "/c"))
  .reduce((last, now) => last.concat(now))
  .reduce((last, now) => now);

Modifier 4n4904z07

Marc
la source
0

J'essaierais de ne pas réinventer la roue. Nous utilisons l' analyse d' objets pour tous nos besoins en matière de traitement de données. C'est conceptuellement très simple, mais permet beaucoup de choses intéressantes. Voici comment vous résoudriez votre question spécifique

Définition des données

const data = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
};

Logique

const objectScan = require('object-scan');

const scanner = (input) => {
  let obj = null;
  objectScan(['*.dinner'], {
    filterFn: (key, value, { parents }) => {
      if (value === 'sushi') {
        obj = parents[0];
      }
    },
    breakFn: () => obj !== null
  })(data);
  return obj;
};

const result = scanner(data);

Production

// => result
{
  "name": "john",
  "dinner": "sushi"
}
Vincent
la source
0

Si vous voulez trouver un objet spécifique via la fonction de recherche, essayez simplement quelque chose comme ceci:

    function findArray(value){

        let countLayer = dataLayer.length;
        for(var x = 0 ; x < countLayer ; x++){

            if(dataLayer[x].user){
                let newArr = dataLayer[x].user;
                let data = newArr[value];
                return data;
            }

        }

        return null;

    }

    findArray("id");

Ceci est un exemple d'objet:

layerObj = {
    0: { gtm.start :1232542, event: "gtm.js"},
    1: { event: "gtm.dom", gtm.uniqueEventId: 52},
    2: { visitor id: "abcdef2345"},
    3: { user: { id: "29857239", verified: "Null", user_profile: "Personal", billing_subscription: "True", partners_user: "adobe"}
}

Le code va itérer et trouver le tableau "user" et cherchera l'objet que vous recherchez à l'intérieur.

Mon problème était lorsque l'index du tableau a changé chaque actualisation de la fenêtre et qu'il était dans le troisième ou le deuxième tableau, mais cela n'a pas d'importance.

A fonctionné à merveille pour moi!

Dans votre exemple, c'est un peu plus court:

function findArray(value){

    let countLayer = Object.length;
    for(var x = 0 ; x < countLayer ; x++){

        if(Object[x].dinner === value){
            return Object[x];
        }

    }

    return null;

}

findArray('sushi');
z3r0
la source