【问题标题】:Best way of basically doing a `where` clause in Javascript?基本上在Javascript中执行“where”子句的最佳方式?
【发布时间】:2011-10-21 00:46:51
【问题描述】:

我正在尝试解析一些发送给我的 JSON,格式为

[{key:value},{key2:value2}, ... ]

在此获取key2 值的最佳方法是什么?有没有办法在不做 for 循环的情况下做到这一点?

【问题讨论】:

  • 为什么不想使用 for 循环?
  • 有人沉迷于 Linq!
  • @vol7 但不能保证它们是这样的
  • @Earlz 为什么要避免 for 循环?出于性能原因?另外,你用什么来解析 JSON?
  • @rsb 我只是想要一些比 for 循环更干净的东西

标签: javascript arrays json


【解决方案1】:

为此对象数组使用 .filter() 方法,例如在您的情况下:

var objArray = [{key:"Hello"},{key2:"Welcome"} ];
var key2Value=objArray.filter(x=>x.key2)[0].key2;

【讨论】:

    【解决方案2】:

    Javascript Array 附带的方法可以满足您的要求 - 无需编写 for 循环即可查找条目。

    你为他们提供你想要的条件。一种紧凑而方便的方法是使用箭头(或“lambda”)函数。在您的情况下,您正在寻找具有特定键的数组条目,因此箭头函数可能如下所示:

    e => e.hasOwnProperty("key2")
    

    在其他一些人的带领下,让我们从假设开始

    var arr = [{key:"value"}, {key2:"value2"}, {key3:"value3"}]
    

    如果您希望数组中最多有一个成员拥有您想要的键,您可以使用find() 函数。它将测试每个数组成员,直到找到一个条件为真的成员,然后返回它。如果没有一个是真的,你会得到undefined

    var foundentry = arr.find(e => e.hasOwnProperty("key2"))
    

    foundentry 将是 undefined 或者它将是您正在寻找的 {key2:"value2"},并且可以从中提取 value2


    如果arr 可以包含多个带有您要查找的密钥的条目,则使用filter() 代替find()。它会返回一组符合您条件的条目。

    var foundarray = arr.filter(e => e.hasOwnProperty("key2"))
    

    【讨论】:

      【解决方案3】:

      不是真的,但创建一个函数来做到这一点并不难。但是,它确实会涉及for 循环。

      为了完整起见,这将是函数:

      function selectWhere(data, propertyName) {
          for (var i = 0; i < data.length; i++) {
              if (data[i][propertyName] !== null) return data[i][propertyName];
          }
          return null;
      }
      

      用法:

      var key2value = selectWhere(data, "key2");
      

      【讨论】:

      • 我不喜欢这个1)使用null2)函数名@ 987654325@;否则,干得好,但考虑使用反向for循环
      【解决方案4】:

      嘿嘿。您可以使用 lodash 库的 .reduce().transform() 函数来实现这一点。 Lodash 比下划线更模块化(下划线大约 5kb,Lodash 大约 17kb),但通常更轻,因为您只包含您需要的特定模块 (请参阅:https://news.ycombinator.com/item?id=9078590 进行讨论)。对于这个演示,我将导入整个模块(通常在后端不是问题): 我为处理数字和非数字参数的任一场景编写了这些 sn-ps。

      https://lodash.com/docs#reduce

      https://lodash.com/docs#transform

      拉入lodash:

      var _ = require('lodash');
      

      _.reduce() 到 where 子句:

      var delim = ' WHERE ', where = _.isEmpty(options) ? '' : _.reduce(options, function(r, v, k) {
          var w = r + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
          delim = ' AND ';
          return w;
      }, '');
      

      _.transform() 到 where 子句:

      var where = _.isEmpty(options) ? '' : ' WHERE ', delim = '';
      _.transform(options, function(r, v, k) {
              where = where + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
              delim = ' AND ';
          });
      

      希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        最佳答案就可以了。这是使用 lodash 的单行版本(大部分与下划线相同):

        var result = _.filter(data, _.partialRight(_.has, 'key2'));
        

        在 lodash 中,select 只是过滤器的别名。我将填充有对象的数据数组传递给它。我使用_.has 作为过滤器函数,因为它完全符合我们的要求:检查属性是否存在。

        _.has 需要两个参数:

        _.has(object, path)
        

        因为_.has 需要两个参数,我知道其中一个始终是常量(路径参数)。我使用_.partialRight 函数来附加常量key2_.partialRight 返回一个需要一个参数的新函数:要检查的对象。新函数检查obj.key2 是否存在。

        【讨论】:

          【解决方案6】:

          jQuery grep() 是 Where 子句的一个很好的类比:

          var array = [{key:1},{key:2}, {key:3}, {key:4}, {key:5}];
          
          var filtered = jQuery.grep(array, function( item, index ) {
            return ( item.key !== 4 && index > 1 );
          });
          

          过滤后的数组将包含两个元素,

           [{key:3}, {key:5}]
          

          【讨论】:

            【解决方案7】:

            这是一个原型是 Array 对象的示例。 注意: 例如 - find 不是这个函数的好名字,而且可能不是所有数组都需要这个

            相反,考虑只使用函数定义并创建一个类似getObjVal 的函数,调用类似getObjVal(arr,'propName'),类似于LaurenT 的答案。

            给定


            var arr = [{key:'value'},{key2:'value2'}];
            

            定义


            // for-loop example
            Array.prototype.find = function (prop){
                                      for(var i=this.length; i--; )
                                         if (typeof this[i][prop] !== 'undefined')
                                            return this[i][prop];
                                      return undefined;
                                   }
            
            // for-each loop example
            Array.prototype.find = function (prop){
                                      for (var i in this)
                                         if ( this.hasOwnProperty(i) && typeof this[i][prop] !== "undefined" ) 
                                            return this[i][prop];
                                      return undefined;
                                   }
            

            用法


            console.log( arr.find('key2') );  // 'value2'
            console.log( arr.find('key3') );  // undefined
            

            【讨论】:

              【解决方案8】:

              试试这个:

              var parsedJSON = JSON.parse(stringJSON);
              var value = parsedJSON['key2'];
              

              【讨论】:

              • 您对 JSON.parse() 有疑问吗?也许尝试 parsedJSON.key2
              • K,所以我看到您使用的是数组而不是有效的 JSON...因此,如果您将有效的字符串传递给函数,您将到达您想去的地方。 JSON.parse() 不包含在某些浏览器中,尤其是 mac 和更旧的浏览器。但是,您可以手动包含它。它返回一个对象,而不是一个数组。而且您可能需要稍微玩一下,但是我确定您正在寻找的内容涉及 JSON.parse()。很高兴我得到了一个否定,而不是那个给您循环的人整个想法是不要使用循环。
              • 它是有效的 JSON。我验证了它。也许我的例子很糟糕。这是真实数据的片段:[{"employername":"FosTech"},{"from":"3/14/2008"},{"to":"5/1/2011"},{"worktype":"programmin" ... ]}
              • K,您是正确的,先生……但是您有一个 JSON 数组,而不是 JSON 对象。数组以方括号开头,对象以花括号开头。更具体地说,您有一个对象数组或一个使用 JSON 表示法的对象字面量数组。一个代表您的数据的 JSON 对象看起来像...{"employername":"FosTech","from":"3/14/2008","to":"5/1/2011","worktype":"‌​programmin",...}
              • K,您是正确的,先生……但是您有一个 JSON 数组,而不是 JSON 对象。数组以方括号开头,对象以花括号开头。更具体地说,您有一个对象数组或一个使用 JSON 表示法的对象字面量数组。代表您的数据的一个 JSON 对象看起来像...{"employername":"FosTech","from":"3/14/2008","to":"5/1/2011","worktype":"‌​programmin",...} 解析格式化为对象的字符串将允许您使用上面的代码将该数据集作为对象引用
              【解决方案9】:

              你不能用数组来做,但你可以用它来做一个像对象一样的关联数组。制作完成后,您可以像哈希一样使用它。

              var arr = [{key:value},{key2:value2}, ... ], obj = {};
              
              for (var i = 0, len = arr.length; i < len; i++) {
                  $.extend(obj, arr[i]);
              }
              
              console.log(obj.key2); // value2
              

              【讨论】:

                【解决方案10】:

                正则表达式 - 没有 for 循环:

                var key2Val = jsonString.match(/\{key2:[^\}]+(?=\})/)[0].substring("{key2:".length);
                

                【讨论】:

                  【解决方案11】:

                  您可以使用Underscore.js 库中的Select 函数。

                  【讨论】:

                  • 作为参考,我的最终结果看起来像 var value2 = _.detect(data, function(d) { return d.key2 != undefined; }).key2;
                  • 这不需要为一个特定情况加载整个库(尽管很小)吗?
                  • @vol7ron 是的。但我敢打赌,一旦你在一个地方使用它,你就会看到其他地方可以使用它。
                  • 它非常轻巧,所以这可能是真的。
                  • 不需要整个库,只需对数组执行filter()
                  猜你喜欢
                  • 1970-01-01
                  • 2019-03-16
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多