JS搜索对象值

时间:2011-12-15 08:25:02

标签: javascript json search

我有一系列同类对象,如此;

[
  {
    "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”)......你明白了。< / p>

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

21 个答案:

答案 0 :(得分:47)

这样的事情:

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 :(得分:32)

所有其他旧答案都使用for循环,现代JavaScript有Object.keys。将它与some,includes和filter相结合,它更好一些。

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

答案 2 :(得分: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

答案 3 :(得分: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' )
        {
            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;
}

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

随意发表评论以改善这一点。

答案 4 :(得分:3)

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

答案 5 :(得分:3)

这是一个propoosal,它使用键给定,或者使用对象的所有属性来搜索值。

&#13;
&#13;
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'));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 6 :(得分:2)

这是现代 Javascript 的一种简洁方式:

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

const query = "lo";
const filteredItems = objects.filter(item => `${item.foo} ${item.bar}`.includes(query));

答案 7 :(得分:2)

这是一个很好的解决方案

$test

<强> EDITED

&#13;
&#13;
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))
&#13;
&#13;
&#13;

答案 8 :(得分:2)

您可以使用此javascript lib,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使用方法“search”扩展全局对象,并返回一个匹配的数组(如果没有找到匹配则返回空数组)。您可以在此处使用XPath Evaluator尝试lib和XPath查询:

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

答案 9 :(得分:2)

以下是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有更多奇特的方法遍历您的对象,但这是基本概念。

干杯!

*编辑:抱歉,我没有仔细阅读您的问题,并修改了代码以返回您请求的对象数组。

答案 10 :(得分:1)

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

答案 11 :(得分:1)

虽然有点晚,但更紧凑的版本可能如下:

target_link_libraries(demo antlr4-runtime)

它可以处理虚假值,例如false,undefined,null以及定义/** * @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; } 方法的所有数据类型,如.toString()等。

答案 12 :(得分:1)

现代JavaScript ?

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

const keyword = 'o';

const results = objects.filter(object => Object.values(object).some(i => i.includes(keyword)));
console.log(results);

// results [{ foo: 'lorem', bar: 'ipsum' },{ foo: 'dolor blor', bar: 'amet blo' }]

答案 13 :(得分: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; })

答案 14 :(得分:0)

我找到了一种可以像所有搜索一样在嵌套对象中进行搜索的方法,例如具有嵌套课程对象的学生列表:

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>

答案 15 :(得分:0)

我需要对一个大对象执行搜索,并返回匹配项的地址,而不仅仅是匹配值本身。

此函数在对象中搜索字符串(或者使用回调函数执行自定义逻辑),并跟踪在对象中找到该值的位置。它还避免了循环引用。

//Search function
var locateInObject = function(obj, key, find, result, currentLocation){
  if(obj === null) return;
  result = result||{done:[],found:{}};
  if(typeof obj == 'object'){
    result.done.push(obj);
  }
  currentLocation = currentLocation||key;
  var keys = Object.keys(obj);
  for(var k=0; k<keys.length; ++k){
    var done = false;
    for(var d=0; d<result.done.length; ++d){
      if(result.done[d] === obj[keys[k]]){
        done = true;
        break;
      }
    }
    if(!done){
      var location = currentLocation+'.'+keys[k];
      if(typeof obj[keys[k]] == 'object'){
        locateInObject(obj[keys[k]], keys[k], find, result, location)
      }else if((typeof find == 'string' && obj[keys[k]].toString().indexOf(find) > -1) || (typeof find == 'function' && find(obj[keys[k]], keys[k]))){
        result.found[location] = obj[keys[k]];
      }
    }
  }
  return result.found;
}

//Test data
var test = {
  key1: {
    keyA: 123,
    keyB: "string"
  },
  key2: {
    keyC: [
      {
        keyI: "string123",
        keyII: 2.3
      },
      "string"
    ],
    keyD: null
  },
  key3: [
    1,
    2,
    123,
    "testString"
  ],
  key4: "123string"
}
//Add a circular reference
test.key5 = test;

//Tests
console.log(locateInObject(test, 'test', 'string'))
console.log(locateInObject(test, 'test', '123'))
console.log(locateInObject(test, 'test', function(val, key){ return key.match(/key\d/) && val.indexOf('string') > -1}))

答案 16 :(得分:0)

今天就解决了这个问题,并使用了epascarello提供的代码的修改版本就可以解决问题,因为当对象包含字符串以外的其他值(例如许多布尔值)时,该版本会遇到麻烦。

console.log('find: ', findIn(arrayOfObjects, searchKey));

const findIn = (arr, searchKey) => {
 return arr.filter(obj => 
  Object.keys(obj).some(key => {
   if (typeof obj[key] === 'string') {
    return obj[key].includes(searchKey);
   }
  })
 );
};

答案 17 :(得分:0)

search(searchText) {
  let arrayOfMatchedObjects = arrayOfAllObjects.filter(object => {
    return JSON.stringify(object)
      .toString()
      .toLowerCase()
      .includes(searchText);
  });
  return arrayOfMatchedObjects;
}

对于像我这样的某些人来说,这可能是非常简单,容易,快速且易于理解的搜索功能。

答案 18 :(得分:0)

我创建了一个易于使用的库,该库可以完全满足您的需求:ss-search

import { search } from "ss-search"

const data = [
  {
       "foo" : "bar",
       "bar" : "sit"
  },
  {
       "foo" : "lorem",
       "bar" : "ipsum"
  },
  {
       "foo" : "dolor",
       "bar" : "amet"
  }
]
const searchKeys = ["foor", "bar"] 
const searchText = "dolor"

const results = search(data, keys, searchText)
// results: [{ "foo": "dolor", "bar": "amet" }]

答案 19 :(得分:0)

您可以使用lodash的 _filter 方法:

return _filter((item) => item.name.includes("fo"),tempObjectHolder);

答案 20 :(得分:0)

简单

const objects = [
     {
     "foo" : "bar",
     "bar" : "sit",
     "date":"2020-12-20"
     },
     {
     "foo" : "lorem",
     "bar" : "ipsum",
     "date":"2018-07-02"
     },
     {
     "foo" : "dolor",
     "bar" : "amet",
     "date":"2003-10-08"
     },
     {
     "foo" : "lolor",
     "bar" : "amet",
     "date":"2003-10-08"
     }
     ];
     
     
     
     const filter = objects.filter(item => {
     const obj = Object.values(item)
     return obj.join("").indexOf('2003') !== -1
     })
     
     console.log(filter)