Javascript JS 在对象值中搜索

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8517089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:20:38  来源:igfitidea点击:

JS search in object values

javascriptjsonsearch

提问by Emphram Stavanger

I have an array of homogeneous objects like so;

我有一个像这样的同类对象数组;

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

I'd like to search these objects' values (not keys) with a keyword, and return an array of objects that contain the keyword in any of the values.

我想用关键字搜索这些对象的值(不是键),并返回一个包含任何值中的关键字的对象数组。

So for example, with a keyword r, I would get all the objects ("baR" in object #1, "loRem" in object #2 and "doloR" in object #3). With a keyword lo, I would get objects 2 and 3 ("LOrem" and "doLOr"), with a, I'd get objects 1 and 3, ("bAr" and "Amet"). With the keyword foohowever, I would get an empty array, since "foo" is a key, and isn't found in any of the values (unlike "bar")... you get the idea.

例如,使用关键字r,我将获得所有对象(对象#1 中的“baR”、对象#2 中的“loRem”和对象#3 中的“doloR”)。使用关键字lo,我将获得对象 2 和 3(“LOrem”和“doLOr”),使用a,我将获得对象 1 和 3(“bAr”和“Amet”)。foo然而,使用关键字,我会得到一个空数组,因为“foo”是一个键,并且在任何值中都找不到(与“bar”不同)......你明白了。

How would I go about doing this? Thanks a lot in advance!

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

回答by techfoobar

Something like this:

像这样的东西:

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

The results array will contain all matched objects.

结果数组将包含所有匹配的对象。

If you search for 'lo', the result will be like:

如果您搜索“lo”,结果将类似于:

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

NEW VERSION - Added trim code, code to ensure no duplicates in result set.

新版本 - 添加了修剪代码,确保结果集中没有重复的代码。

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

回答by epascarello

All the other old answers use a for in loop, modern JavaScript has Object.keys. Combine that with some, includes, and filter and it is a bit nicer.

所有其他旧答案都使用 for in 循环,现代 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"));

Or with ES6

或者使用 ES6

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

回答by vsync

The searchfunction will return all objects which contain a value which has contains the search query

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

回答by General Omosco

This is a cool solution that works perfectly

这是一个很酷的解决方案,效果很好

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

EDITED

已编辑

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


// array.filter loops through your array and create a new array returned as Boolean value given out "true" from eachIndex(item) function 

var item = array.filter((item)=>eachIndex(item));

//var item = array.filter();



function eachIndex(e){
console.log("Looping each index element ", e)
return e.title.toLowerCase().includes("this".toLowerCase())
}

console.log("New created array that returns \"true\" value by eachIndex ", item)

回答by Nina Scholz

This is a proposal which uses the key if given, or all properties of the object for searching a value.

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

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

回答by Gera

As a Javascripter Lv. 1 I just learned to search for strings in objects with this:

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

I know is far from perfect but it is useful.

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

Feel free to comment in order to improve this.

请随时发表评论以改进这一点。

回答by Michael Robinson

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

回答by lincolnberryiii

Here is the answer in 100% PURE JavaScript:

以下是 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>

There are, of course, more fancy ways to traverse your object using JQuery, but this is the basic concept.

当然,还有更多奇特的方法可以使用 JQuery 遍历对象,但这是基本概念。

Cheers!

干杯!

*EDIT:Sorry, I didn't read your question carefully enough, and modified the code to return an array of objects as you requested.

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

回答by Hakan Bilgin

You can use this javascript lib, DefiantJS (http://defiantjs.com), with which you can filter matches using XPath on JSON structures. To put it in JS code:

您可以使用这个 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" }
]
*/

Here is a working fiddle;
http://jsfiddle.net/hbi99/2kHDZ/

这是一个工作小提琴;
http://jsfiddle.net/hbi99/2kHDZ/

DefiantJS extends the global object with the method "search" and returns an array with matches (empty array if no matches were found). You can try out the lib and XPath queries using the XPath Evaluator here:

DefiantJS 使用“search”方法扩展全局对象并返回一个包含匹配项的数组(如果没有找到匹配项,则为空数组)。您可以在此处使用 XPath Evaluator 尝试 lib 和 XPath 查询:

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

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

回答by Nadeem Jamali

Although a bit late, but a more compact versionmay be the following:

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

/**
* @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;
}

It can handle falsy valueslike false, undefined, null and all the data types that define .toString()method like number, booleanetc.

它可以处理假值,如 false、undefined、null 和所有定义.toString()方法的数据类型等number, boolean