假设我有一个对象:
[
{
'title': "some title"
'channel_id':'123we'
'options': [
{
'channel_id':'abc'
'image':'http://asdasd.com/all-inclusive-block-img.jpg'
'title':'All-Inclusive'
'options':[
{
'channel_id':'dsa2'
'title':'Some Recommends'
'options':[
{
'image':'http://www.asdasd.com' 'title':'Sandals'
'id':'1'
'content':{
...
我想找到id为1的一个对象。是否有类似这样的函数?我可以使用Underscore的_.filter
方法,但我必须从顶部开始并过滤掉。
答案 0 :(得分:66)
递归是你的朋友。我更新了函数以考虑属性数组:
function getObject(theObject) {
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = getObject(theObject[i]);
if (result) {
break;
}
}
}
else
{
for(var prop in theObject) {
console.log(prop + ': ' + theObject[prop]);
if(prop == 'id') {
if(theObject[prop] == 1) {
return theObject;
}
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
result = getObject(theObject[prop]);
if (result) {
break;
}
}
}
}
return result;
}
更新了jsFiddle:http://jsfiddle.net/FM3qu/7/
答案 1 :(得分:17)
如果要在搜索对象时获取id为1的第一个元素,可以使用此函数:
function customFilter(object){
if(object.hasOwnProperty('id') && object["id"] == 1)
return object;
for(var i=0; i<Object.keys(object).length; i++){
if(typeof object[Object.keys(object)[i]] == "object"){
var o = customFilter(object[Object.keys(object)[i]]);
if(o != null)
return o;
}
}
return null;
}
如果你想获得id为1的所有元素,那么(id为1的所有元素都存储在结果中):
function customFilter(object, result){
if(object.hasOwnProperty('id') && object.id == 1)
result.push(object);
for(var i=0; i<Object.keys(object).length; i++){
if(typeof object[Object.keys(object)[i]] == "object"){
customFilter(object[Object.keys(object)[i]], result);
}
}
}
答案 2 :(得分:11)
对我有用的是这种懒惰的方法,而不是算法上的懒惰;)
if( JSON.stringify(object_name).indexOf("key_name") > -1 ) {
console.log("Key Found");
}
else{
console.log("Key not Found");
}
答案 3 :(得分:5)
我通过谷歌搜索找到了类似功能的页面。根据Zach和regularmike提供的工作,我创建了另一个适合我需要的版本 BTW,teriffic work Zah和regularmike! 我会在这里发布代码:
obj
它的作用是找到targetProp
内的任何对象,其属性名称和值与targetValue
和finalResults
匹配,并将其推送到A
A
B
B
B
C
数组。
以下是玩游戏的小提琴:
set()
答案 4 :(得分:2)
我为此目的创建了库:this solution
您可以使用var foundObject = findFirst(rootObject, 'options', { 'id': '1' });
这样的方法:
foundObject
现在http://MYIP/documents/animals document 1.pdf
http://MYIP/documents/animals document 2.pdf
...
变量存储了对您正在寻找的对象的引用。
答案 5 :(得分:2)
使用键和谓词改进@haitaka答案
library(dplyr)
library(tidyr)
library(ggplot2)
DAT %>%
gather(Day, Value, -person, -Score) %>%
mutate(Day = factor(Day, levels = c("Mon", "Tues", "Wed", "Thurs", "Fri"))) %>%
ggplot(aes(Day, Value)) +
geom_point(aes(color = Score))
因此可以将其调用为:
function deepSearch (object, key, predicate) {
if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object
for (let i = 0; i < Object.keys(object).length; i++) {
if (typeof object[Object.keys(object)[i]] === "object") {
let o = deepSearch(object[Object.keys(object)[i]], key, predicate)
if (o != null) return o
}
}
return null
}
或
var result = deepSearch(myObject, 'id', (k, v) => v === 1);
这是jsFiddle:http://jsfiddle.net/ktdx9es7
答案 6 :(得分:1)
我想建议对Zach / RegularMike的答案进行修正(但没有“声誉”可以发表评论!)。我发现那里的解决方案是一个非常有用的基础,但是在我的应用程序中却遇到了麻烦,因为如果数组中有字符串,它将递归地为字符串中的每个 character 调用函数(这导致IE11和Edge浏览器失败, “堆栈空间不足”错误)。我的简单优化是将“对象”子句递归调用中使用的相同测试添加到“数组”子句中的测试:
if (arrayElem instanceof Object || arrayElem instanceof Array) {
因此,我的完整代码(现在正在查找特定键的所有实例,因此与原始要求略有不同)是:
// Get all instances of specified property deep within supplied object
function getPropsInObject(theObject, targetProp) {
var result = [];
if (theObject instanceof Array) {
for (var i = 0; i < theObject.length; i++) {
var arrayElem = theObject[i];
if (arrayElem instanceof Object || arrayElem instanceof Array) {
result = result.concat(getPropsInObject(arrayElem, targetProp));
}
}
} else {
for (var prop in theObject) {
var objProp = theObject[prop];
if (prop == targetProp) {
return theObject[prop];
}
if (objProp instanceof Object || objProp instanceof Array) {
result = result.concat(getPropsInObject(objProp, targetProp));
}
}
}
return result;
}
答案 7 :(得分:1)
function getPropFromObj(obj, prop) {
let valueToFindByKey;
if (!Array.isArray(obj) && obj !== null && typeof obj === "object") {
if (obj.hasOwnProperty(prop)) {
valueToFindByKey = obj[prop];
console.log(valueToFindByKey);
} else {
let i;
for (i = 0; i < Object.keys(obj).length; i++) {
getPropFromObj(obj[Object.keys(obj)[i]], prop);
}
}
}
return null;
}
const objToInvestigate = {
employeeInformation: {
employees: {
name: "surya",
age: 27,
job: "Frontend Developer",
},
},
};
getPropFromObj(objToInvestigate, "name");
答案 8 :(得分:1)
您可以在递归函数中使用 javascript some
函数。 some 的优点是一旦孩子被建立就停止循环。不要使用在大数据中会变慢的地图。
const findChild = (array, id) => {
let result;
array.some(
(child) =>
(child.id === id && (result = child)) ||
(result = findChild(child.options || [], id))
);
return result;
};
findNode(array, 1)
答案 9 :(得分:1)
另一种递归解决方案,适用于数组/列表和对象,或两者的混合:
function deepSearchByKey(object, originalKey, matches = []) {
if(object != null) {
if(Array.isArray(object)) {
for(let arrayItem of object) {
deepSearchByKey(arrayItem, originalKey, matches);
}
} else if(typeof object == 'object') {
for(let key of Object.keys(object)) {
if(key == originalKey) {
matches.push(object);
} else {
deepSearchByKey(object[key], originalKey, matches);
}
}
}
}
return matches;
}
用法:
let result = deepSearchByKey(arrayOrObject, 'key'); // returns an array with the objects containing the key
答案 10 :(得分:1)
前一段时间,我制作了一个小库find-and
,该库可以在this one上使用,用于以lodash方式处理嵌套对象。有一个returnFound
函数,它返回找到的对象,如果发现多个对象,则返回一个对象数组。
例如
const findAnd = require('find-and');
const a = [
{
'title': "some title",
'channel_id':'123we',
'options': [
{
'channel_id':'abc',
'image':'http://asdasd.com/all-inclusive-block-img.jpg',
'title':'All-Inclusive',
'options':[
{
'channel_id':'dsa2',
'title':'Some Recommends',
'options':[
{
'image':'http://www.asdasd.com',
'title':'Sandals',
'id':'1',
'content':{},
},
],
},
],
},
],
},
];
findAnd.returnFound(a, {id: '1'});
返回
{
'image':'http://www.asdasd.com',
'title':'Sandals',
'id':'1',
'content':{},
}
答案 11 :(得分:1)
我会尽量不要重新发明轮子。我们将object-scan用于所有数据处理需求。从概念上讲,它很简单,但是可以容纳很多很酷的东西。这是解决特定问题的方法
const data = [{
'title': "some title",
'channel_id': '123we',
'options': [{
'channel_id': 'abc',
'image': 'http://asdasd.com/all-inclusive-block-img.jpg',
'title': 'All-Inclusive',
'options': [{
'channel_id': 'dsa2',
'title': 'Some Recommends',
'options': [{
'image': 'http://www.asdasd.com',
'title': 'Sandals',
'id': '1',
'content': {}
}]
}]
}]
}];
const objectScan = require('object-scan');
const scanner = (input) => {
let obj = null;
objectScan(['**.id'], {
filterFn: (key, value, { parents }) => {
if (value === '1') {
obj = parents[0];
}
},
breakFn: () => obj !== null
})(input);
return obj;
};
const result = scanner(data);
// result =>
{
"image": "http://www.asdasd.com",
"title": "Sandals",
"id": "1",
"content": {}
}
答案 12 :(得分:1)
改进的答案以考虑对象内的循环引用。 它还显示到达目的地所需的路径。
在此示例中,我正在搜索一个我知道位于全局对象内某处的iframe:
const objDone = []
var i = 2
function getObject(theObject, k) {
if (i < 1 || objDone.indexOf(theObject) > -1) return
objDone.push(theObject)
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = getObject(theObject[i], i);
if (result) {
break;
}
}
}
else
{
for(var prop in theObject) {
if(prop == 'iframe' && theObject[prop]) {
i--;
console.log('iframe', theObject[prop])
return theObject[prop]
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array) {
result = getObject(theObject[prop], prop);
if (result) {
break;
}
}
}
}
if (result) console.info(k)
return result;
}
运行以下命令:
getObject(reader, 'reader')
最后给出了以下输出和iframe元素:
iframe // (The Dom Element)
_views
views
manager
rendition
book
reader
注意:路径的顺序相反reader.book.rendition.manager.views._views.iframe
答案 13 :(得分:0)
@Iulian Pinzaru的回答几乎正是我所需要的,但是如果您的对象具有任何null值,它将无法正常工作。此版本已解决该问题。
function deepSearch (object, key, predicate) {
if (object.hasOwnProperty(key) && predicate(key, object[key]) === true) return object
for (let i = 0; i < Object.keys(object).length; i++) {
const nextObject = object[Object.keys(object)[i]];
if (nextObject && typeof nextObject === "object") {
let o = deepSearch(nextObject, key, predicate)
if (o != null) return o
}
}
return null
}
答案 14 :(得分:0)
只需使用递归函数。
请参见下面的示例:
const data = [
{
title: 'some title',
channel_id: '123we',
options: [
{
channel_id: 'abc',
image: 'http://asdasd.com/all-inclusive-block-img.jpg',
title: 'All-Inclusive',
options: [
{
channel_id: 'dsa2',
title: 'Some Recommends',
options: [
{
image: 'http://www.asdasd.com',
title: 'Sandals',
id: '1',
content: {},
}
]
}
]
}
]
}
]
function _find(collection, key, value) {
for (const o of collection) {
for (const [k, v] of Object.entries(o)) {
if (k === key && v === value) {
return o
}
if (Array.isArray(v)) {
const _o = _find(v, key, value)
if (_o) {
return _o
}
}
}
}
}
console.log(_find(data, 'channel_id', 'dsa2'))
答案 15 :(得分:0)
另一种(有点愚蠢的)选择是利用JSON.stringify
的自然递归性质,并在字符串化过程中将其传递给在每个嵌套对象上运行的replacer function:
const input = [{
'title': "some title",
'channel_id': '123we',
'options': [{
'channel_id': 'abc',
'image': 'http://asdasd.com/all-inclusive-block-img.jpg',
'title': 'All-Inclusive',
'options': [{
'channel_id': 'dsa2',
'title': 'Some Recommends',
'options': [{
'image': 'http://www.asdasd.com',
'title': 'Sandals',
'id': '1',
'content': {}
}]
}]
}]
}];
console.log(findNestedObj(input, 'id', '1'));
function findNestedObj(entireObj, keyToFind, valToFind) {
let foundObj;
JSON.stringify(input, (_, nestedValue) => {
if (nestedValue && nestedValue[keyToFind] === valToFind) {
foundObj = nestedValue;
}
return nestedValue;
});
return foundObj;
};
答案 16 :(得分:0)
fucntion getPath(obj, path, index = 0) {
const nestedKeys = path.split('.')
const selectedKey = nestedKeys[index]
if (index === nestedKeys.length - 1) {
return obj[selectedKey]
}
if (!obj.hasOwnProperty(selectedKey)) {
return {}
}
const nextObj = obj[selectedKey]
return Utils.hasPath(nextObj, path, index + 1)
}
不客气 创建人:Gorillaz
答案 17 :(得分:-1)
这段代码允许您获取用户定义的键中的JSON中的所有对象。
function main(obj = {}, property){
const views = [];
function traverse(o) {
for (var i in o) {
if(i === property) views.push(o[i]);
if (!!o[i] && typeof(o[i])=="object") {
console.log(i, o[i]);
traverse(o[i]);
} else {
console.log(i, o[i]);
}
}
}
traverse(obj);
return views;
}
这里是一个例子:
const obj = {
id: 'id at level 1',
level2: {
id: 'id at level 2',
level3: {
id: 'id at level 3',
level4: {
level5: {
id: 'id at level 5'
}
}
}
},
text: ''
}
main(obj, 'id');
答案 18 :(得分:-12)
如果您已经在使用下划线,请使用_.find()
_.find(yourList, function (item) {
return item.id === 1;
});