【问题标题】:Get all values from an Object who's key ends with a particular pattern从一个以特定模式结尾的对象中获取所有值
【发布时间】:2015-12-28 06:43:24
【问题描述】:

我正在尝试从一个对象中检索所有键值,其中键名以(比如 _abc)结尾。

我的尝试

obj = {p1_abc: 1, p2_abc: 2, p3_def: 3, p4_abc: 4, p5_def: 5}

required_keys = jQuery.map(Object.keys(obj), function(val, i){
  if(val.indexOf("_abc") != -1)
    return val;
});
//required_keys = ['p1_abc', 'p2_abc', 'p4_abc']

required_values = jQuery.map(required_keys, function(v, i){
  return(obj[v]);
});
//required_values = [1, 2, 4]

这里,required_values 包含了我需要的值,但是我觉得整个代码有点难看。有没有一种干净的方法来实现这一点?

【问题讨论】:

    标签: javascript jquery arrays object


    【解决方案1】:

    有几分钟的空闲时间,这似乎是一个很好的问题来介绍iterators

    以下是用 ES5 编写的示例,但它也可以在加载了垫片的 ES3 中工作。

    function makeEntriesIterator(object) {
      var keys = Object.keys(object);
      var nextKey = 0;
      return {
        next: function next() {
          if (nextKey < keys.length) {
            var key = keys[nextKey];
            var iterator = {
              value: [key, object[key]],
              done: false
            };
            nextKey += 1;
            return iterator;
          }
          return {
            value: undefined,
            done: true
          };
        }
      };
    }
    
    var obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    };
    
    var iterator = makeEntriesIterator(obj);
    var next = iterator.next();
    var matches = [];
    while (!next.done) {
      if (next.value[0].slice(-4) === '_abc') {
        matches.push(next.value);
      }
      next = iterator.next();
    }
    document.getElementById('out').textContent = JSON.stringify(matches, null, 2);
    console.log(matches);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.4.1/es5-shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
    
    <pre id="out"></pre>

    在 ES6 中,您可以使用for..of 代替while,并且数组有迭代器valuesentrieskeys,默认Symbol.iteratorvalues

    'use strict';
    
    const obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    };
    
    const matches = [];
    for (let key of Object.keys(obj)) {
      if (key.endsWith('_abc')) {
        matches.push([key, obj[key]]);
      }
    }
    document.getElementById('out').textContent = JSON.stringify(matches, null, 2);
    console.log(matches);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.4.1/es5-shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.0/es6-shim.js"></script>
    <pre id="out"></pre>

    ES7 将为对象引入迭代器,例如entries,然后事情变得更加清晰,因为您不需要使用Object.keys。但这暂时还不能演示。

    'use strict';
    
    const obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    };
    
    const matches = [];
    for (let [key, value] of obj) {
      if (key.endsWith('_abc')) {
        matches.push([key, value]);
      }
    }
    

    【讨论】:

    【解决方案2】:

    你应该使用reduce同时过滤和减少项目

    var obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    }
    var regex = /_abc$/;
    var required_values = Object.keys(obj).reduce(function(sum, key) {
      if (regex.test(key)) {
        sum.push(obj[key]);
      }
      return sum;
    }, []);
    
    console.log(required_values);
    &lt;script src="https://getfirebug.com/firebug-lite-debug.js"&gt;&lt;/script&gt;

    【讨论】:

    • 在纯 ES5 中,reduce 是解决这个问题的最佳方法,而不是 filtermap 的组合。
    • 这将匹配 _abc 字符串的任何位置,而不仅仅是在末尾。
    • @Xotic750 解决了这个问题,最初想用正则表达式来做
    【解决方案3】:

    首先使用Object.keys()从对象中获取所有属性,然后使用Array.prototype.filter()过滤所需属性的数组,最后使用括号运算符从对象中收集所有值,并使用Array.prototype.map()返回不错的数组。

    var obj = { p1_abc: 1, p2_abc: 2, p3_def: 3, p4_abc: 4, p5_def: 5, _abcp6: 6 },
        required_values = Object.keys(obj).filter(function (a) {
            return /_abc$/.test(a);
        }).map(function (a) {
            return obj[a];
        });
    
    document.write('<pre>' + JSON.stringify(required_values, 0, 4) + '</pre>');

    【讨论】:

    • 另一个匹配 _abc 在字符串中的任何位置,而不仅仅是在末尾。
    【解决方案4】:

    你可以在一个.map() 中做到这一点

    obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    }
    
    required_keys = jQuery.map(Object.keys(obj), function(val, i) {
      if (val.indexOf("_abc") != -1) {
        return obj[val];
      }
    
    });
    document.write(required_keys);
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    或者如果你想要键/值,你可以这样做

    obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    }
    
    required_keys = jQuery.map(Object.keys(obj), function(val, i) {
      if (val.indexOf("_abc") != -1) {
        return {[val]:obj[val]};
      }
    
    });
    document.write(JSON.stringify(required_keys));
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 这两种解决方案也将匹配字符串中任何位置的_abc,而不仅仅是在末尾。
    【解决方案5】:

    尝试使用for..in循环,RegExp.prototype.test()RegExp/_abc$/来匹配以"_abc"结尾的对象的属性

    var obj = {
      p1_abc: 1,
      p2_abc: 2,
      p3_def: 3,
      p4_abc: 4,
      p5_def: 5
    };
    
    for (prop in obj) {
      if (/_abc$/.test(prop))
        console.log(obj[prop]) // do stuff with `prop` , `obj[prop]`
    }

    【讨论】:

    • 值得注意的是,OP 表示 where key name ends with (say _abc),但当前使用的 RegExp 将测试字符串中任何位置的 _abc
    • @Xotic750 “值得注意的是,OP 说明了密钥名称以(比如 _abc)结尾的位置,但当前使用的 RegExp 将在字符串中的任何位置测试 _abc。”抓住。可以将RegExp 调整为/_abc$/
    • 是的,可以解决它。 ;)
    • 一个不错且简单的 ES3 解决方案。
    【解决方案6】:

    当您标记 Jquery 时,您可以使用 $.each()

    var obj = {p1_abc: 1, p2_abc: 2, p3_def: 3, p4_abc: 4, p5_def: 5}
    $.each(obj , function(k , v){
      if (k.indexOf("_abc") != -1){
            alert(v)
      };
    })
    

    Working Demo

    返回数组

    var obj = {p1_abc: 1, p2_abc: 2, p3_def: 3, p4_abc: 4, p5_def: 5}
    var requireKeys = [];
    $.each(obj , function(k , v){
      if (k.indexOf("_abc") != -1){
          requireKeys.push(v);
      };
    })
    alert(requireKeys);
    

    Working Demo

    【讨论】:

    • 这些也匹配字符串中任何位置的_abc,而不仅仅是在末尾。
    【解决方案7】:

    如果您有一个大型数据集,我会更喜欢“性能”而不是“干净”。这不是“最干净”的代码,但它比任何其他解决方案(到目前为止)都具有更高的性能。

    function getValues (obj) {
      var values = []
      for(var key in obj){
        if (key.substr(key.length - 4) === '_abc') {
          values.push(obj[key])
        }
      }
      return values
    }
    

    【讨论】:

    • 这个匹配字符串末尾的abc,可以是_abc,也可以是xabc
    【解决方案8】:

    这里是findKey函数实现。

    它返回第一个元素的键谓词返回truthy for而不是元素本身。

    /**
     * @param {Object} collection The collection to inspect.
     * @param {Function} predicate The function.
     * @returns {*} Returns the key, else `undefined`. 
     */
    var findKey = function(object, predicate) {
      let result;
      if (object == null) {
        return result;
      }
      Object.keys(object).some(function(key) {
        const value = object[key]
        if (predicate(value, key, object)) {
          result = key;
          return true;
        }
      })
      return result;
    }
    

    用法

    //Example usage
    var collections = {
      brand_category_3320: 1133,
      brand_category_3321: 2245
    };
    
    var r = findKey(collections, function(o, key, context) {
      if (key.indexOf(3320) > -1) {
        return true;
      }
      return false;
    });
    
    console.log('The r is =', r);
    

    【讨论】:

      【解决方案9】:

          obj = {
            p1_abc: 1,
            p2_abc: 2,
            p3_def: 3,
            p4_abc: 4,
            p5_def: 5
          }
      
          required_data = Object.keys(obj).map(function(val, i) {
            if (val.indexOf("_abc") != -1)
              return {
                [val]: obj[val]
              };
          });
      
          console.log(required_data);

      将产生一个新的reuired对象数组,另外你可以删除jQuery。

      【讨论】:

      • 值得注意的是,这将返回一个与Object.keys 长度相同的数组,但不需要的数据将是undefined。因此,您可能需要通过filter 运行它,然后才能在您的程序中使用它。
      • 还匹配字符串中任何位置的_abc,而不仅仅是在末尾。
      猜你喜欢
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 2014-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      相关资源
      最近更新 更多