按嵌套数组深处的键查找

IT技术 javascript underscore.js
2021-02-09 12:24:11

假设我有一个对象:

[
    {
        '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方法,但我必须从顶部开始并向下过滤。

6个回答

递归是你的朋友。我更新了函数以说明属性数组:

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/

如果选项中有多个对象,这将不起作用
2021-03-12 12:24:11
那里。我之前提到过它需要更新以考虑数组,所以你去。
2021-03-19 12:24:11
Zack 我稍微修改了你的代码,它现在运行良好。非常感谢!看来我目前无法访问 jsfiddle。一旦有效,我将分享我的更改
2021-03-19 12:24:11
固定的。我添加了 result 变量和 else 逻辑。更新后的 jsFiddle 显示它工作正常。
2021-04-02 12:24:11
但是等等,看看我的代码,选项可以有很多对象 [{},{}]。这将如何工作?
2021-04-07 12:24:11

对我有用的是这种懒惰的方法,而不是算法上的懒惰;)

if( JSON.stringify(object_name).indexOf("key_name") > -1 ) {
    console.log("Key Found");
}
else{
    console.log("Key not Found");
}
我喜欢它! JSON.stringify(object).includes(text)
2021-03-13 12:24:11
您如何看待使用它:if( JSON.stringify(object_name).indexOf('{"key_name":') > -1 ) {包括左大括号、双引号和 JSON.stringify 添加的冒号?我认为这可能是一个很好的双重检查,以确保 key_name 实际上是一个键,而不是以某种方式在“值”部分。
2021-03-14 12:24:11
可能很好,但是在值中某处具有该 key_name 的测试失败。也不返回包含 id 的对象
2021-03-16 12:24:11
@Ranga...同意,此解决方案仅在您只需要检查对象中是否存在键,前提是其中一个值中不存在 key_name 时才有效......虽然,我们可以修改代码如果我们必须确保它只存在于键中,则在 indexOf 函数内的键名周围包含 '"'。(同样,带有 '"' 的 key_name 不应该出现在值中。
2021-04-06 12:24:11
这个发现,如果关键是存在,但OP询问如何获得其id属性为1.此值会使回答的对象stackoverflow.com/questions/2631001/...(除了一个事实,即它匹配字符串是否存在于 JSON 中的任何位置,而不是它有键。
2021-04-06 12:24:11

如果要在搜索对象时获取第一个 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);
        }
    }
}
您的解决方案比@regularmike 建议的更好,因为我可以通过添加键和值搜索来自定义它。它对你的有效,对他的无效。 jsfiddle.net/76fp54xt 工作示例
2021-04-03 12:24:11

另一个(有点愚蠢的)选项是利用 的自然递归性质JSON.stringify,并在字符串化过程中向它传递一个在每个嵌套对象上运行替换函数

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(entireObj, (_, nestedValue) => {
    if (nestedValue && nestedValue[keyToFind] === valToFind) {
      foundObj = nestedValue;
    }
    return nestedValue;
  });
  return foundObj;
};

真的很聪明
2021-03-19 12:24:11
我喜欢你的想法 :) 我只是认为如果我们已经找到了结果,如果中断递归运行替换函数,它看起来会更好。例如,我们可以使用throw. jsfiddle.net/w4vs36hm
2021-04-06 12:24:11

我通过谷歌搜索类似的功能找到了这个页面。基于 Zach 和 regularmike 提供的工作,我创建了另一个适合我需要的版本。
顺便说一句,Zah 和regularmike 干得好!我会在这里发布代码:

function findObjects(obj, targetProp, targetValue, finalResults) {

  function getObject(theObject) {
    let result = null;
    if (theObject instanceof Array) {
      for (let i = 0; i < theObject.length; i++) {
        getObject(theObject[i]);
      }
    }
    else {
      for (let prop in theObject) {
        if(theObject.hasOwnProperty(prop)){
          console.log(prop + ': ' + theObject[prop]);
          if (prop === targetProp) {
            console.log('--found id');
            if (theObject[prop] === targetValue) {
              console.log('----found porop', prop, ', ', theObject[prop]);
              finalResults.push(theObject);
            }
          }
          if (theObject[prop] instanceof Object || theObject[prop] instanceof Array){
            getObject(theObject[prop]);
          }
        }
      }
    }
  }

  getObject(obj);

}

它的作用是找到其中的任何对象,obj其属性名称和值与targetProp匹配targetValue,并将其推送到finalResults数组中。这是要玩的 jsfiddle:https ://jsfiddle.net/alexQch/5u6q2ybc/

这可以通过returningfinalResults数组而不是接受另一个变量作为要写入的输入来进一步改进
2021-04-07 12:24:11