搜索包含值的 json 对象键,然后取消设置它

Posted

技术标签:

【中文标题】搜索包含值的 json 对象键,然后取消设置它【英文标题】:Searching json object key containing value, then unset it 【发布时间】:2012-08-23 04:35:24 【问题描述】:

我正在寻找一种方法来搜索 JSON 对象以检查它是否包含给定值,如果存在,则取消设置它。

我的数据结构如下(附注释):

// Search within the 'seats' array for a given 'guestID', if it exists, unset it
tables = [
   
      "_id":
         $oid: "one"
      ,
      "seats":[
          "guestId":"01" ,
          "guestId":"02" ,
          "guestId":"03" 
      ]
   ,
   
      "_id":
         $oid: "two"
      ,
      "seats":[
          "guestId":"11" ,
          "guestId":"12" ,
          "guestId":"13" 
      ]
   
]

我在这个项目中使用下划线,我尝试使用_.pluck(tables, 'seats'),然后使用 _.foreach,但我不得不嵌套多个 _.foreach 语句来访问席位数组进行搜索,我不确定这是否是最佳实践。有没有我不知道的更简单的方法?

这个数据是从 mongolab REST api 返回的。这是我应该在我的初始 XHR 请求中做的事情,而不是获取一个大对象然后尝试在客户端解析它吗?

如果这是一个 SQL 请求,我将能够执行类似 select tables.seats where guestId = XXX 的操作

【问题讨论】:

您到底在寻找什么?您的输入和期望输出是什么? 如果一张桌子包含所需的座位,您是要删除桌子,还是删除座位? 【参考方案1】:

每当我过去遇到这种情况时,递归搜索功能一直是无价的......这是我的一个我躺在身边(我通过添加删除方法扩展它):

function o ( target ) 
  /// if an instance of o has been created, then handle it
  if ( this instanceof o ) 
    /// O INSTANCE:
    /// an instance of o acts like a reference or pointer 
    /// to how the value it targets was reached.
    this.value = target;
    this.key = arguments[1];
    this.parent = arguments[2];
    this.toString = function() return 'o('+this.key+' = '+this.value+')';
  
  /// if no instance being created fall back to the 'scan object' code
  else 
    /// RECURSIVE CODE:
    /// the _ function is responsible for accepting the 
    /// attributeName and attributeValue search
    var _ = function ( key, value, modifier ) 
      var i, v, tar = ( modifier ? modifier.target : target ), items = [];
      /// if we are dealing with an o instance, handle slightly differently
      if ( tar instanceof o ) 
        for ( i in tar.value ) 
          /// check to see if our current key and value 
          /// match our search terms
          if ( _.test( i, (v=tar.value[i]), key, value ) ) 
            items.push(new o(v, i, tar));
          ;
        ;
      
      /// if no o instance treat as a normal object or array
      else 
        for ( i in tar ) 
          if ( (v = tar[i]) ) 
            /// if we are an instance of o, recurse to actually 
            /// check the items within
            if ( v instanceof o ) 
              items = items.concat( _( key, value, target:v ) );
            
            /// check to see if our current key and value match 
            /// our search terms
            else if ( _.test( i, v, key, value ) ) 
              items.push(new o(v, i, tar));
            ;
          ;
        ;
      ;
      /// if in modifier mode, don't rely on storing in scope, 
      /// return the calculated items instead
      if ( modifier ) 
        return items;
      
      else 
        /// update what we are targeting
        target = items;
        /// return our underscore function
        return _;
      ;
    ;
    /// FUNCTION DECLARATIONS:
    /// a quick test to see if the key and value match (or either or)
    _.test = function ( i,v,key,value ) 
      var havekey = ( key !== null && key !== undefined ),
          haveval = ( value !== null && value !== undefined ),
          passkey = ( havekey && (i == key || key === '*') ),
          passval = ( haveval && (v == value || value === '*') );
      return ( havekey && haveval && passkey && passval ) || 
        ( havekey && !haveval && passkey ) || 
        ( haveval && !havekey && passval );
    ;
    /// calculate the path needed to reach the object within the structure
    _.path = function () 
      var i = target.length, paths = [], path, cur, last;
      while ( i-- ) 
        cur = target[i]; path = [];
        do last = cur; if ( cur instanceof o ) path.unshift( cur.key );  
          while( (cur = cur.parent) );
        paths.push(path.join('/'));
      ;
      return ( paths.length == 1 ? paths[0] : paths );
    ;
    /// remove the item we are targeting by stepping back 
    /// and deleting ourselves from the previous parent
    _.remove = function ( removeEntireObject ) 
      var i = target.length, paths, path, cur, last;
      while ( i-- ) 
        cur = target[i];
        /// remove the object that has the found attribute
        if ( removeEntireObject ) 
          if ( cur.parent.parent ) 
            cur.parent.parent.value[cur.parent.key] = null;
            delete cur.parent.parent.value[cur.parent.key];
          
        
        /// otherwise remove only the targeted attribute
        else 
          cur.parent.value[cur.key] = null;
          delete cur.parent.value[cur.key];
        
      ;
      return _;
    ;
    /// a useful function for backwards navigation
    _.parent = function () 
      var i = target.length, cur, items = [], values = [];
      while ( i-- ) 
        cur = target[i];
        /// remove the object that has the found attribute
        if ( cur && cur.parent ) 
          /// store the values as we go so we can 
          /// spot and remove duplicated parents
          if ( values.indexOf(cur.parent.value) === -1 ) 
            items.push(cur.parent);
            values.push(cur.parent.value);
          
        
      ;
      target = items;
      return _;
    
    /// slimple debugging
    _.alert = function () 
      var i = target.length, cur;
      while ( i-- ) 
        cur = target[i];
        alert(cur);
      ;
      return _;
    ;
    return _;
  ;
;

示例用法:

/// remove only the guestId object with a value '01'

o(tables)('*')('seats')('*')('guestId', '01').remove( true );

或:

/// remove the 'guestIds' object in the first slot for either seat

o(tables)('*')('seats')(0)('guestId', '*').parent().remove();

或:

/// remove all 'guestIds' from the first seat

o(tables)(0)('seats')('*')('guestId').parent().remove();

解释:

您必须始终先致电o(my_object_to_parse)。 传递一个参数相当于attributeName 搜索。 传递两个参数充当attributeNameattributeValue 搜索。 * 充当简单的通配符,可用于处理基本数组。 * 可以用作attributeNameattributeValue。 每个连续的请求都会在结构中进一步移动一层。

我已经有一段时间没有使用此代码了,因此它可能不是 100% 无错误或最佳的。但是,它似乎适用于您的特定用例……并且它还设法处理了我在测试时扔给它的所有内容。除了.remove().parent().path().alert() 之外,它应该很容易扩展更多方法,并且最好添加一些错误检查。

【讨论】:

以上是关于搜索包含值的 json 对象键,然后取消设置它的主要内容,如果未能解决你的问题,请参考以下文章

取消设置数组为 PHP 中的对象添加键

搜索并取消设置 JSON 对象

PostgreSQL 查询包含特定键值的 json 对象中的行

从具有不同值的逗号分隔 JSON 对象填充 html 下拉列表

visualstudio取消设置为启动项目

取消设置对象 PHP 的所有实例