Поиск JS в значениях объекта
У меня есть массив однородных объектов, например:
[
{
"foo" : "bar",
"bar" : "sit"
},
{
"foo" : "lorem",
"bar" : "ipsum"
},
{
"foo" : "dolor",
"bar" : "amet"
}
]
Я хотел бы искать значения этих объектов (не ключей) с ключевым словом и возвращать массив объектов, которые содержат ключевое слово, в любом из значений.
Так, например, с ключевым словом r
, я бы получил все объекты ( "baR" в объекте # 1, "loRem" в объекте # 2 и "dloR" в объекте # 3). С ключевым словом lo
я бы получил объекты 2 и 3 ( "LOrem" и "doLOr" ), с a
, я бы получил объекты 1 и 3 ( "bAr" и "Amet" ). С ключевым словом foo
, однако, я бы получил пустой массив, так как "foo" является ключом и не встречается ни в одном из значений (в отличие от "bar" )... вы получаете идею.
Как мне это сделать? Большое спасибо заранее!
Ответы
Ответ 1
Что-то вроде этого:
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]);
}
}
}
Массив результатов будет содержать все согласованные объекты.
Если вы ищете 'lo', результат будет выглядеть следующим образом:
[{ foo="lorem", bar="ipsum"}, { foo="dolor", bar="amet"}]
НОВАЯ ВЕРСИЯ - Добавлен код обложки, код для обеспечения отсутствия дубликатов в наборе результатов.
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 '));
Ответ 2
Все остальные старые ответы используют цикл for for, современный JavaScript имеет Object.keys
. Объедините это с некоторыми, включает и фильтрует, и это немного лучше.
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"));
Ответ 3
Функция search
возвращает все объекты, содержащие значение, содержащее поисковый запрос
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
Ответ 4
Как Javascripter Lv. 1 Я только что научился искать строки в объектах с этим:
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;
}
Я знаю, далек от совершенства, но это полезно.
Не стесняйтесь комментировать, чтобы улучшить это.
Ответ 5
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"]
Ответ 6
Вот ответ на 100% PURE 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>
Есть, конечно, более причудливые способы перемещения вашего объекта с помощью JQuery, но это основная концепция.
Ура!
* EDIT: Извините, я недостаточно внимательно прочитал ваш вопрос и изменил код, чтобы вернуть массив объектов по вашему запросу.
Ответ 7
Вы можете использовать эту javascript lib, DefiantJS (http://defiantjs.com), с помощью которой вы можете фильтровать совпадения с использованием XPath на структурах JSON. Чтобы поместить его в код 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" }
]
*/
Вот рабочая скрипка;
http://jsfiddle.net/hbi99/2kHDZ/
DefiantJS расширяет глобальный объект методом "поиск" и возвращает массив со спичками (пустой массив, если совпадений не найдено). Вы можете опробовать запросы lib и XPath с помощью XPath Evaluator:
http://www.defiantjs.com/#xpath_evaluator
Ответ 8
Ниже разделяется для конкретного заданного свойства
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];
}
//использование ниже
result=$localStorage.searchContent(cabNo,appDataObj.getAll(),function() { dummy.cabDriverName; })
Ответ 9
Это пропозиционер, который использует ключ, если задан, или все свойства объекта для поиска значения.
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; }
Ответ 10
Еще одно изменение, использующее ES6
, это то, что я использую.
// 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);
});