JS поиск по значениям объекта - PullRequest
38 голосов
/ 15 декабря 2011

У меня есть массив однородных объектов, например, так:

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

Я бы хотел найти значения этих объектов (не ключей) по ключевому слову и вернуть массив объектов, которые содержат ключевое словов любом из значений.

Так, например, с ключевым словом r я бы получил все объекты («baR» в объекте № 1, «loRem» в объекте № 2 и «doloR» вобъект № 3).С ключевым словом lo я бы получил объекты 2 и 3 ("LOrem" и "doLOr"), с a я бы получил объекты 1 и 3 ("bAr" и "Amet").Однако с ключевым словом foo я бы получил пустой массив, так как "foo" является ключом и не найден ни в одном из значений (в отличие от "bar") ... идея понятна.

Как бы я поступил так?Заранее большое спасибо!

Ответы [ 14 ]

49 голосов
/ 15 декабря 2011

Примерно так:

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 '));
33 голосов
/ 30 ноября 2016

Все остальные старые ответы используют цикл 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"));

или с ES6

function filterIt(arr, searchKey) {
  return arr.filter(obj => Object.keys(obj).some(key => obj[key].includes(searchKey)));
}
5 голосов
/ 15 декабря 2011

Функция 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 голосов
/ 28 ноября 2014

Как 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;
}

Я знаю, что это далеко от совершенства, но это полезно.

Не стесняйтесь комментировать, чтобы улучшить это.

3 голосов
/ 04 мая 2018

Это классное решение, которое отлично работает

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)
3 голосов
/ 30 ноября 2016

Это пропоосал, который использует ключ, если он задан, или все свойства объекта для поиска значения.

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; }
3 голосов
/ 15 декабря 2011
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"]
2 голосов
/ 05 января 2014

Вы можете использовать эту библиотеку JavaScript, 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

2 голосов
/ 15 декабря 2011

Вот ответ в 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, но это основная концепция.

Cheers!

* РЕДАКТИРОВАТЬ: Извините, я недостаточно внимательно прочитал ваш вопрос и изменил код так, чтобы он возвращал массив объектов по вашему запросу.

1 голос
/ 26 апреля 2018

Хотя и немного поздно, но более компактная версия может быть следующей:

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

Может обрабатывать ложные значения , такие как false, undefined, null и все типы данных, которые определяют метод .toString(), например number, boolean и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...