2011-12-15 69 views
15

我有一个像这样的同类对象数组;JS对象值搜索

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

我喜欢与关键字搜索这些对象的值(未键),并返回包含在任何的值的关键字对象的数组编号。例如,使用关键字r,我将获得所有对象(对象#1中的“baR”,对象#2中的“loRem”和对象#3中的“doloR”)。关键字lo,我会得到对象2和3(“LOrem”和“doLOr”),a,我会得到对象1和3(“bAr”和“Amet”)。然而,使用关键字foo,我会得到一个空数组,因为“foo”是一个键,并且在任何值中都找不到(与“bar”不同)...您会明白。

我该怎么做呢?提前感谢!

+0

如果你正在使用jQuery那么它的http://stackoverflow.com/questions/5288833/how-to-search-json-tree-with-jquery – 2011-12-15 08:27:21

回答

30

事情是这样的:

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

编辑for循环一点。现在,如果您设置为搜索'lo',则输出将为: [{foo =“lorem”},{foo =“dolor”}] – techfoobar 2011-12-15 08:41:34

+0

这是最接近的,因为其他函数返回字符串数组,对象数组。但是,对象只包含匹配的值,而它应该包含整个原始对象。你能修改你的脚本来反映这个吗? – 2011-12-15 10:19:01

+1

已更新我的答案。希望这是你打算实现的。 – techfoobar 2011-12-15 12:22:28

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有一个bug。 'search(subject,objects)'... – vsync 2011-12-15 08:35:50

+0

@vsync:thanks :) – 2011-12-15 08:37:58

5

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

2

下面是100%的回答纯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遍历对象的方法更多,但这是基本概念。

干杯!

*编辑:对不起,我没有仔细阅读您的问题,并且修改了代码以根据您的要求返回对象数组。

2

您可以使用此JavaScript库DefiantJS(http://defiantjs.com),通过它可以使用JSON结构上的XPath过滤匹配项。把它放在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延伸,该方法的全局对象的“搜索”,并返回用火柴的阵列(如果没有找到匹配结果空数组)。你可以在这里使用XPath计算器试用lib和XPath查询:

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

3

作为一个JavaScript程序员吕。 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; 
} 

我知道远非完美,但它是有用的。

随时评论,以改善这一点。

0

下面具体给定的属性

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

所有其他老的答案在循环使用的,现代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"));

或用ES6

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

这是使用如果给钥匙,或者用于搜索值的对象的所有属性propoosal。

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

只需使用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); 
});