web-dev-qa-db-fra.com

Recherche JS dans les valeurs d'objet

J'ai un tableau d'objets homogènes comme celui-ci;

[
  {
    "foo" : "bar",
    "bar" : "sit"
  },
  {
    "foo" : "lorem",
    "bar" : "ipsum"
  },
  {
    "foo" : "dolor",
    "bar" : "amet"
  }
]

Je voudrais rechercher les valeurs de ces objets (pas les clés) avec un mot clé et renvoyer un tableau d'objets contenant le mot clé dans l'une des valeurs.

Ainsi, par exemple, avec un mot clé r, j'obtiendrais tous les objets ("baR" dans l'objet n ° 1, "loRem" dans l'objet n ° 2 et "doloR" dans l'objet n ° 3). Avec un mot clé lo, j'obtiendrais les objets 2 et 3 ("LOrem" et "doLOr"), avec a, les objets 1 et 3 ("bAr" et "Amet"). Cependant, avec le mot clé foo, j'obtiendrais un tableau vide, car "foo" est une clé et ne figure dans aucune des valeurs (contrairement à "bar") ... vous voyez l'idée.

Comment pourrais-je m'y prendre? Merci beaucoup d'avance!

30
Emphram Stavanger

Quelque chose comme ça:

var objects = [
  {
    "foo" : "bar",
    "bar" : "sit"
  },
  {
    "foo" : "lorem",
    "bar" : "ipsum"
  },
  {
    "foo" : "dolor",
    "bar" : "amet"
  }
];

var results = [];

var toSearch = "lo";

for(var i=0; i<objects.length; i++) {
  for(key in objects[i]) {
    if(objects[i][key].indexOf(toSearch)!=-1) {
      results.Push(objects[i]);
    }
  }
}

Le tableau de résultats contiendra tous les objets correspondants.

Si vous recherchez 'lo', le résultat sera le suivant:

[{ foo="lorem", bar="ipsum"}, { foo="dolor", bar="amet"}]

NOUVELLE VERSION - Ajout du code de rognage et du code pour éviter les doublons dans l'ensemble de résultats

function trimString(s) {
  var l=0, r=s.length -1;
  while(l < s.length && s[l] == ' ') l++;
  while(r > l && s[r] == ' ') r-=1;
  return s.substring(l, r+1);
}

function compareObjects(o1, o2) {
  var k = '';
  for(k in o1) if(o1[k] != o2[k]) return false;
  for(k in o2) if(o1[k] != o2[k]) return false;
  return true;
}

function itemExists(haystack, needle) {
  for(var i=0; i<haystack.length; i++) if(compareObjects(haystack[i], needle)) return true;
  return false;
}

var objects = [
  {
    "foo" : "bar",
    "bar" : "sit"
  },
  {
    "foo" : "lorem",
    "bar" : "ipsum"
  },
  {
    "foo" : "dolor blor",
    "bar" : "amet blo"
  }
];

function searchFor(toSearch) {
  var results = [];
  toSearch = trimString(toSearch); // trim it
  for(var i=0; i<objects.length; i++) {
    for(var key in objects[i]) {
      if(objects[i][key].indexOf(toSearch)!=-1) {
        if(!itemExists(results, objects[i])) results.Push(objects[i]);
      }
    }
  }
  return results;
}

console.log(searchFor('lo '));
40
techfoobar

Toutes les autres anciennes réponses utilisent une boucle in, le JavaScript moderne a Object.keys. Combinez cela avec des filtres, des filtres, et c’est un peu plus agréable. 

var a = [{
  name: 'xyz',
  grade: 'x'
}, {
  name: 'yaya',
  grade: 'x'
}, {
  name: 'x',
  frade: 'd'
}, {
  name: 'a',
  grade: 'b'
}];

function filterIt(arr, searchKey) {
  return arr.filter(function(obj) {
    return Object.keys(obj).some(function(key) {
      return obj[key].includes(searchKey);
    })
  });
}

console.log("find 'x'", filterIt(a,"x"));
console.log("find 'a'", filterIt(a,"a"));
console.log("find 'z'", filterIt(a,"z"));

Ou avec ES6

function filterIt(arr, searchKey) {
  return arr.filter(obj => Object.keys(obj).some(key => obj[key].includes(searchKey)));
}
29
epascarello

La fonction search renvoie tous les objets contenant une valeur contenant la requête de recherche.

function search(arr, s){
    var matches = [], i, key;
    
    for( i = arr.length; i--; )
        for( key in arr[i] )
            if( arr[i].hasOwnProperty(key) && arr[i][key].indexOf(s) > -1 )
                matches.Push( arr[i] );  // <-- This can be changed to anything

    return matches;
};

// dummy data
var items = [
      {
        "foo" : "bar",
        "bar" : "sit"
      },
      {
        "foo" : "lorem",
        "bar" : "ipsum"
      },
      {
        "foo" : "dolor",
        "bar" : "amet"
      }
];
    
var result = search(items, 'lo'); // search "items" for a query value
console.log(result); // print the result

5
vsync

En tant que Javascripter Lv. 1 Je viens d'apprendre à rechercher des chaînes dans des objets avec ceci:

function isThere( a_string, in_this_object )
{
    if( typeof a_string != 'string' )
    {
        return false;
    }

    for( var key in in_this_object )
    {
        if( typeof in_this_object[key] == 'object' || typeof in_this_object[key] == 'array' )
        {
            if ( isThere( a_string, in_this_object[key] ) )
            {
                return true;
            }
        }
        else if( typeof in_this_object[key] == 'string' )
        {
            if( a_string == in_this_object[key] )
            {
                return true;
            }
        }
    }

    return false;
}

Je sais que c'est loin d'être parfait mais c'est utile.

N'hésitez pas à commenter pour améliorer cela.

4
Gera

Ceci est une proposition qui utilise la clé si donnée, ou toutes les propriétés de l'objet pour rechercher une valeur.

function filter(array, value, key) {
    return array.filter(key
        ? a => a[key] === value
        : a => Object.keys(a).some(k => a[k] === value)
    );
}

var a = [{ name: 'xyz', grade: 'x' }, { name: 'yaya', grade: 'x' }, { name: 'x', frade: 'd' }, { name: 'a', grade: 'b' }];


console.log(filter(a, 'x'));
console.log(filter(a, 'x', 'name'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

3
Nina Scholz
var search(subject, objects) {

    var matches = [];
    var regexp = new RegExp(subject, 'g');

    for (var i = 0; i < objects.length; i++) {
        for (key in objects[i]) {
            if (objects[i][key].match(regexp)) matches.Push(objects[i][key]);
        }
    }
    return matches;
};

var items = [
  {
    "foo" : "bar",
    "bar" : "sit"
  },
  {
    "foo" : "lorem",
    "bar" : "ipsum"
  },
  {
    "foo" : "dolor",
    "bar" : "amet"
  }
];

search('r', items);    // ["bar", "lorem", "dolor"]
3
Michael Robinson

Vous pouvez utiliser cette bibliothèque javascript, DefiantJS ( http://defiantjs.com ), avec laquelle vous pouvez filtrer les correspondances à l’aide de XPath sur des structures JSON. Pour le mettre en code JS:

    var data = [
       { "foo": "bar",   "bar": "sit" },
       { "foo": "lorem", "bar": "ipsum" },
       { "foo": "dolor", "bar": "amet" }
    ],
    res1 = JSON.search( data, '//*[contains(name(), 'r')]/..' ),
    res2 = JSON.search( data, '//*[contains(., 'lo')]' );

/*
res1 = [
    { "foo": "bar",   "bar": "sit" },
    { "foo": "lorem", "bar": "ipsum" },
    { "foo": "dolor", "bar": "amet" }
]
*/

/*
res2 = [
    { "foo": "lorem", "bar": "ipsum" },
    { "foo": "dolor", "bar": "amet" }
]
*/

Voici un violon qui fonctionne.
http://jsfiddle.net/hbi99/2kHDZ/

DefiantJS étend l'objet global avec la méthode "search" et renvoie un tableau avec des correspondances (tableau vide si aucune correspondance n'a été trouvée). Vous pouvez essayer les requêtes lib et XPath à l'aide de l'évaluateur XPath ici:

http://www.defiantjs.com/#xpath_evaluator

2
Hakan Bilgin

Voici la réponse en JavaScript 100% PURE:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
<script type="text/javascript">

var mySet = [
    {
    "foo" : "bar",
    "bar" : "sit"
    },
    {
    "foo" : "lorem",
    "bar" : "ipsum"
    },
    {
    "foo" : "dolor",
    "bar" : "amet"
    }
];

function queryObject(needle, set){
    var results = new Array();
    for(index=0;index<set.length;index++){
        for(key in set[index]){
            if(set[index][key].indexOf(needle) > -1){
                results.Push(set[index]);
            }
        }
    }

    if(results.length){
        return JSON.stringify(results);
    }else{
        return "No match!";
    }
}

</script>
</head>
<body>
<form>
    <input type="text" id="Prompt" onFocus="this.value='';" value="Type your query HERE" size="20" onKeyDown="document.getElementById('submit').disabled = false;">
    <input id="submit" type="button" value="Find in Object" onClick="var Prompt=document.getElementById('Prompt'); if(Prompt.value){document.getElementById('output').innerHTML = queryObject(Prompt.value, mySet);}else{Prompt.value='Type your query HERE';}" disabled="disabled">
    <div id="output"></div>
</form>
</body>
</html>

Il existe bien sûr des manières plus sophistiquées de parcourir votre objet à l'aide de JQuery, mais c'est le concept de base.

À votre santé!

* EDIT: Désolé, je n'ai pas lu votre question assez attentivement et j'ai modifié le code pour renvoyer un tableau d'objets comme vous l'avez demandé.

2
lincolnberryiii

C'est une solution cool qui fonctionne parfaitement

const array = [{"title":"tile hgfgfgfh"},{"title":"Wise cool"},{"title":"titlr DEytfd ftgftgfgtgtf gtftftft"},{"title":"This is the title"},{"title":"yeah this is cool"},{"title":"tile hfyf"},{"title":"tile ehey"}];

var item = array.filter(item=>item.title.toLowerCase().includes('this'));

 alert(JSON.stringify(item))

&EACUTE;DIT&EACUTE;

const array = [{"title":"tile hgfgfgfh"},{"title":"Wise cool"},{"title":"titlr DEytfd ftgftgfgtgtf gtftftft"},{"title":"This is the title"},{"title":"yeah this is cool"},{"title":"tile hfyf"},{"title":"tile ehey"}];


// array.filter loops through your array and create a new array returned as Boolean value given out "true" from eachIndex(item) function 

var item = array.filter((item)=>eachIndex(item));

//var item = array.filter();



function eachIndex(e){
console.log("Looping each index element ", e)
return e.title.toLowerCase().includes("this".toLowerCase())
}

console.log("New created array that returns \"true\" value by eachIndex ", item)

1
General Omosco

Juste une autre variante utilisant ES6, c'est ce que j'utilise.

// searched keywords    
const searchedWord = "My searched exp";

// array of objects
let posts = [
    {
        text_field: "lorem ipsum doleri imet",
        _id: "89789UFJHDKJEH98JDKFD98"
    }, 
    {
        text_field: "ipsum doleri imet",
        _id: "JH738H3JKJKHJK93IOHLKL"
];

// search results will be pushed here
let matches = [];

// regular exp for searching
let regexp = new RegExp(searchedWord, 'g');

// looping throuth posts to fing the Word
posts.forEach((post) => {
    if (post["text_field"].match(regexp)) matches.Push(post);
});
1
MoolsBytheway

J'ai trouvé un moyen de rechercher un objet imbriqué comme dans toute recherche, par exemple une liste d'étudiants ayant un objet de leçon imbriqué:

var students=[{name:"ALi",family:"romandeh",age:18,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]},
   {name:"hadi",family:"porkar",age:48,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]},
   {name:"majid",family:"porkar",age:30,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]}
   ];
  
    function searchInChild(objects, toSearch){
        var _finded=false;
        for(var i=0; i<objects.length; i++) {
            for(key in objects[i]) {
                if(objects[i][key]!=null && typeof(objects[i][key] )!="boolean" && typeof(objects[i][key] )!="number"){
                    if (typeof objects[i][key] == 'object') {
                        _finded= searchInChild(objects[i][key],toSearch);

                    }
                    else if(objects[i][key].indexOf(toSearch)!=-1) {
                        _finded=true;
                    }
                }
            }
        }
        return _finded;
    }
    function findNested(objects, toSearch) {
        var _results=[];
        for(var i=0; i<objects.length; i++) {
            for(key in objects[i]) {
                if(objects[i][key]!=null && typeof(objects[i][key] )!="boolean" && typeof(objects[i][key] )!="number"){
                    if (typeof objects[i][key] == 'object') {
                        if(searchInChild(objects[i][key],toSearch)){
                            _results.Push(objects[i]);
                        }
                    }
                    else if(objects[i][key].indexOf(toSearch)!=-1) {
                        _results.Push(objects[i]);
                    }
                }
            }
        }

        return _results;

    }
    $('.quickSearch').on('click',function(){
          var _inputSeach=$('#evertingSearch').val();
          if(_inputSeach!=''){
          var _finded=findNested(students,_inputSeach);
          $('.count').html(_finded.length);}
    
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<span>
<pre><code>
       var students=[{name:"ALi",family:"romandeh",age:18,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]},
   {name:"hadi",family:"porkar",age:48,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]},
   {name:"majid",family:"rezaeiye",age:30,curse:[
   {lesson1:"arabic"},
   {lesson2:"english"},
   {lesson3:"history"}
   ]}
   ];
</code></pre>

<span>

<input id="evertingSearch" placeholder="Search on students" />
<input type="button" class="quickSearch" value="search" />
<lable>count:</lable><span class="count"></span>


</body>



</html>

0
Mahdi Porkar

Bien qu'un peu tard, mais un version plus compacte peut être le suivant:

/**
* @param {string} quickCriteria Any string value to search for in the object properties.
* @param {any[]} objectArray The array of objects as the search domain
* @return {any[]} the search result
*/
onQuickSearchChangeHandler(quickCriteria, objectArray){

   let quickResult = objectArray.filter(obj => Object.values(obj).some(val => val?val.toString().toLowerCase().includes(quickCriteria):false));

   return quickResult;
}

Il peut gérer les valeurs faussaires comme false, undefined, null et tous les types de données qui définissent la méthode .toString() comme number, boolean etc.

0
Nadeem Jamali

Ci-dessous partagé pour une propriété donnée

searchContent:function(s, arr,propertyName){
            var matches = [];
            var propertyNameString=this.propertyNameToStr(propertyName);
            for (var i = arr.length; i--; ){
                if((""+Object.getOwnPropertyDescriptor(arr[i], propertyNameString).value).indexOf(s) > -1)
                    matches.Push(arr[i]);
            }
            return matches;
        },
    propertyNameToStr: function (propertyFunction) {
            return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1];
    }

// utilisation comme ci-dessous

result=$localStorage.searchContent(cabNo,appDataObj.getAll(),function() { dummy.cabDriverName; })
0
Syed Raheem Uddin