2011-12-15 83 views
15

Tôi có một mảng các đối tượng đồng nhất như vậy;Tìm kiếm JS trong các giá trị đối tượng

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

Tôi muốn tìm kiếm các giá trị của các đối tượng này (không phải khóa) bằng từ khóa và trả về một mảng đối tượng chứa từ khóa trong bất kỳ giá trị nào.

Ví dụ: với từ khóa r, tôi sẽ nhận tất cả các đối tượng ("baR" trong đối tượng # 1, "loRem" trong đối tượng # 2 và "doloR" trong đối tượng # 3). Với một từ khóa lo, tôi sẽ nhận được các đối tượng 2 và 3 ("LOrem" và "doLOr"), với a, tôi muốn lấy các đối tượng 1 và 3, ("bAr" và "Amet"). Tuy nhiên, với từ khóa foo, tôi sẽ nhận được một mảng trống, vì "foo" là khóa và không được tìm thấy trong bất kỳ giá trị nào (không giống như "thanh") ... bạn có ý tưởng.

Tôi làm cách nào để thực hiện việc này? Cảm ơn rất nhiều trước!

+0

Nếu bạn đang sử dụng jQuery thì đó là một bản sao có thể có của http://stackoverflow.com/questions/5288833/how-to-search-json-tree-with-jquery –

Trả lời

30

Something như thế này:

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

Mảng kết quả sẽ chứa tất cả đối tượng phù hợp.

Nếu bạn tìm kiếm cho 'lo', kết quả sẽ như thế nào:

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

NEW VERSION - Nhập mã trim, mã để đảm bảo không có bản sao trong tập kết quả.

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

Đã chỉnh sửa vòng lặp for một chút. Bây giờ nếu bạn đặt toSearch thành 'lo', đầu ra sẽ là: [{foo = "lorem"}, {foo = "dolor"}] – techfoobar

+0

Đây là gần nhất, vì các hàm khác trả về mảng chuỗi và trả về mảng các đối tượng. Tuy nhiên, các đối tượng chỉ chứa giá trị phù hợp, trong khi nó phải chứa toàn bộ đối tượng gốc. Bạn có thể sửa đổi kịch bản của bạn để phản ánh điều này? –

+1

Đã cập nhật câu trả lời của tôi. Hy vọng đây là những gì bạn đang có ý định đạt được. – 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 có một lỗi. 'tìm kiếm (chủ đề, đối tượng)' ... – vsync

+0

@vsync: cảm ơn :) –

5

Các search hàm sẽ trả lại tất cả đối tượng có chứa một giá trị trong đó có chứa các truy vấn tìm kiếm

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

điều này là nhanh chóng, không có regex và kiểm tra để đảm bảo không có không có phím prototyped với 'hasOwnProperty'. – vsync

+0

nhanh chóng tìm kiếm nội dung trong tất cả các thuộc tính quan trọng, –

2

Dưới đây là câu trả lời trong vòng 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> 

Có, tất nhiên, nhiều cách ưa thích để đi qua đối tượng của bạn bằng cách sử dụng JQuery, nhưng đây là khái niệm cơ bản.

Chúc mừng!

* CHỈNH SỬA: Rất tiếc, tôi không đọc đủ câu hỏi của bạn và sửa đổi mã để trả về một mảng đối tượng như bạn yêu cầu.

+0

Nếu bạn muốn làm cho hàm hoạt động tổng quát hơn, bạn sẽ loại bỏ biến khai báo biến và chuyển nó tới hàm làm đối số thay thế; ví dụ: 'hàm queryObject (kim, bộ)' – lincolnberryiii

+1

Xin lỗi, tôi không đọc đủ câu hỏi của bạn và sửa đổi mã để trả về một mảng các đối tượng như bạn yêu cầu. – lincolnberryiii

2

Bạn có thể sử dụng javascript javascript này, DefiantJS (http://defiantjs.com), mà bạn có thể lọc các kết quả phù hợp bằng cách sử dụng XPath trên cấu trúc JSON. Để đặt mã vào mã 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" } 
] 
*/ 

Đây là một số công việc;
http://jsfiddle.net/hbi99/2kHDZ/

DefiantJS mở rộng đối tượng chung với phương thức "tìm kiếm" và trả về một mảng có kết quả phù hợp (mảng trống nếu không tìm thấy kết quả phù hợp).Bạn có thể thử các truy vấn lib và XPath sử dụng XPath Evaluator đây:

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

3

Là một Javascripter Lv. 1 Tôi vừa học cách tìm kiếm các chuỗi trong các đối tượng với điều này:

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

Tôi biết là hoàn hảo nhưng hữu ích.

Hãy bình luận để cải thiện điều này.

+0

Tôi đã lấy của bạn và sử dụng nó để lặp qua một đối tượng ko quan sát được. Tôi phải thay đổi nhưng nó đã hoạt động. THanks – boca

0

Dưới đây chia sẻ cho bất động sản được cụ thể

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

// sử dụng như sau

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

Tất cả các câu trả lời cũ khác sử dụng cho trong vòng lặp, JavaScript hiện đại có Object.keys. Kết hợp với một số, bao gồm, và bộ lọc và nó là một chút đẹp hơn.

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

Hoặc với ES6

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

Với mã này từ @epascarello, bạn có thể tìm thấy đối tượng có khóa chứa khóa tìm kiếm, nhưng nếu bạn đang tìm kiếm tổng số, bạn nên thay đổi hàm thử nghiệm của phương thức "some" bằng cách sử dụng "===" thay thế "bao gồm ": một số (key => obj [key] === searchKey) – DrWaky

0

Đây là một propoosal trong đó sử dụng phím nếu được, hoặc tất cả các thuộc tính của đối tượng để tìm kiếm một giá trị.

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

Chỉ cần một biến thể sử dụng ES6, đây là những gì tôi sử dụng.

// 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); 
}); 
Các vấn đề liên quan