2011-12-15 8 views
15

Ho una matrice di oggetti omogenei come tale;Ricerca JS nei valori dell'oggetto

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

mi piacerebbe cercare i valori di questi oggetti (non chiavi) con una parola chiave, e restituire un array di oggetti che contengono la parola chiave in uno qualsiasi dei valori.

Quindi, ad esempio, con una parola chiave r, otterrei tutti gli oggetti ("baR" nell'oggetto # 1, "loRem" nell'oggetto # 2 e "doloR" nell'oggetto # 3). Con una parola chiave lo, otterrei gli oggetti 2 e 3 ("LOrem" e "doLOr"), con a, otterrei gli oggetti 1 e 3, ("bAr" e "Amet"). Con la parola chiave foo, tuttavia, otterrei un array vuoto, dato che "foo" è una chiave, e non si trova in nessuno dei valori (a differenza di "bar") ... si ottiene l'idea.

Come faccio a fare questo? Grazie mille in anticipo!

+0

Se stai usando jQuery allora è un possibile duplicato di http://stackoverflow.com/questions/5288833/how-to-search-json-tree-with-jquery –

risposta

30

Qualcosa di simile a questo:

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

La matrice risultati conterrà tutti gli oggetti corrispondenti.

Se si cerca 'lo', il risultato sarà come:

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

NUOVA VERSIONE - Codice assetto aggiunta, il codice per garantire l'assenza di duplicati in set di risultati.

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 ')); 
+1

Modificato un po 'il ciclo for. Ora se si imposta toSearch su "lo", l'output sarà: [{foo = "lorem"}, {foo = "dolor"}] – techfoobar

+0

Questo è il più vicino, poiché le altre funzioni restituiscono array di stringhe e questo restituisce matrici di oggetti. Tuttavia, gli oggetti contengono solo il valore corrispondente, mentre dovrebbe contenere l'intero oggetto originale. Potresti modificare il tuo script per riflettere questo? –

+1

Ho aggiornato la mia risposta. Spero che questo sia ciò che intendevi raggiungere. – techfoobar

2
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"] 
+1

u ha un bug. 'search (subject, objects)' ... – vsync

+0

@vsync: thanks :) –

5

La funzione search restituirà tutti gli oggetti che contengono un valore che ha contiene la query di ricerca

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

+0

questo è veloce, senza regex, E un controllo per assicurarsi no non ci sono chiavi prototipate con 'hasOwnProperty'. – vsync

+0

veloce per cercare il contenuto in tutte le proprietà chiave, –

2

Ecco la risposta in 100% puro JavaScript:

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

Ci sono, naturalmente, altri modi fantastici per attraversare il tuo oggetto usando JQuery, ma questo è il concetto di base.

Cheers!

* EDIT: Siamo spiacenti, non ho letto la domanda con sufficiente attenzione e ho modificato il codice per restituire una serie di oggetti come richiesto.

+0

Se si desidera rendere la funzione più genericamente dinamica, rimuovere la dichiarazione del set di variabili e passarla invece alla funzione come argomento; cioè: 'function queryObject (needle, set)' – lincolnberryiii

+1

Spiacente, non ho letto abbastanza attentamente la tua domanda e ho modificato il codice per restituire una serie di oggetti come richiesto. – lincolnberryiii

2

È possibile utilizzare questo javascript lib, DefiantJS (http://defiantjs.com), con il quale è possibile filtrare le corrispondenze utilizzando XPath nelle strutture JSON. Per inserirlo nel codice 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" } 
] 
*/ 

Ecco un violino funzionante;
http://jsfiddle.net/hbi99/2kHDZ/

DefiantJS estende l'oggetto globale con il metodo di "ricerca" e restituisce un array con le partite (array vuoto se non sono stati trovati partite).È possibile provare le query XPath e lib utilizzando il XPath Evaluator qui:

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

3

Come Javascripter Lv. 1 Ho appena imparato a cercare stringhe negli oggetti con questo:

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') 
     { 
      return isThere(a_string, in_this_object[key]) 
     } 
     else if(typeof in_this_object[key] == 'string') 
     { 
      if(a_string == in_this_object[key]) 
      { 
       return true; 
      } 
     } 
    } 

    return false; 
} 

So che è tutt'altro che perfetto ma è utile.

Sentitevi liberi di commentare per migliorare questo.

+0

Ho preso il tuo e l'ho usato per scorrere un oggetto osservabile ko. Ho dovuto apportare modifiche ma ha funzionato. THanks – boca

0

Sotto condiviso per specifica data proprietà

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

// uso come di seguito

result=$localStorage.searchContent(cabNo,appDataObj.getAll(),function() { dummy.cabDriverName; }) 
18

Tutte le altre risposte vecchie utilizzare una per in loop, moderno JavaScript ha Object.keys. Combinalo con alcuni, include e filtri ed è un po 'più bello.

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"));

O con ES6

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

Con questo codice di @epascarello puoi trovare un oggetto che ha una chiave che contiene il searchKey, ma se stai cercando una corrispondenza totale dovresti cambiare la funzione di test del metodo "some" usando "===" invece "include ": alcuni (chiave => obj [chiave] === searchKey) – DrWaky

0

Questa è una propoosal che utilizza la chiave se dato, o tutte le proprietà dell'oggetto per la ricerca di un valore.

function filter(array, value, key) { 
 
    return array.filter(key ? function (a) { 
 
     return a[key] === value; 
 
    } : function (a) { 
 
     return Object.keys(a).some(function (k) { 
 
      return 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; }

0

solo un'altra variazione usando ES6, questo è quello che uso.

// 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); 
}); 
Problemi correlati