Поиск JS в значениях объекта

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

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

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

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

Как мне это сделать? Большое спасибо заранее!

Ответы

Ответ 1

Что-то вроде этого:

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

Ответ 2

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

Ответ 3

Функция 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

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

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

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

Ответ 5

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

Ответ 6

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

Ура!

* EDIT: Извините, я недостаточно внимательно прочитал ваш вопрос и изменил код, чтобы вернуть массив объектов по вашему запросу.

Ответ 7

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

Ответ 8

Ниже разделяется для конкретного заданного свойства

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

Ответ 9

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

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

Ответ 10

Еще одно изменение, использующее 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);
});