skip to Main Content

I’m trying to recreate the Underscore pluck function using pure JS. However, I keep getting an array of undefineds being returned, instead of the actual values from the properties of the objects in an array.

Checking another thread here I found that you could reproduce it in jQuery with the following code…

$.pluck = function(arr, key) { 
    return $.map(arr, function(e) { return e[key]; }) 
}

…however I am having difficulty just reproducing this in pure JS. I tried the following, however this is just returning an array of undefineds for me.

var pluck = function(arr,key){
  var newArr = [];
  for (var i = 0, x = arr.length; i < x; i++){
    if (arr[i].hasOwnProperty(key)){
      newArr.push(arr[i].key)
    }
  }
  return newArr;
}

So, the goal would be the following, except instead of using the underscore _.pluck, just use a JS function name, eg. var pluck = function(arr,key){…}

var Tuts = [{name : 'NetTuts', niche : 'Web Development'}, {name : 'WPTuts', niche : 'WordPress'}, {name : 'PSDTuts', niche : 'PhotoShop'}, {name : 'AeTuts', niche : 'After Effects'}];
var niches = _.pluck(Tuts, 'niche');

console.log(niches);

// ["Web Development", "WordPress", "PhotoShop", "After Effects"]

Could someone steer me in the right direction?

10

Answers


  1. You are so close. You need to change:

    newArr.push(arr[i].key);
    

    to:

    newArr.push(arr[i][key]);
    

    Consider this:

    var obj = { myKey: 'my Value', theKey: 'another value' };
    var theKey = 'myKey';
    
    alert(obj.theKey); // another value
    alert(obj[theKey]); // my Value
    // You can also send in strings here:
    alert(obj['theKey']); // another value
    

    Hope you get my point.

    Login or Signup to reply.
  2. You can do it with the native JavaScript .map():

    Array.prototype.pluck = function(key) {
      return this.map(function(object) { return object[key]; });
    };
    

    edit — modifying built-in prototype objects should be done with care; a better way to add the function (should you be OK with the idea of doing so in general) would be with Object.defineProperty so that it can be made non-enumerable:

    Object.defineProperty(Array.prototype, "pluck", {
        value: function(key) {
            return this.map(function(object) { return object[key]; });
        }
    });
    
    Login or Signup to reply.
  3. Here’s a working solution

    function pluck(array,key){
      var a = [],
         i1 = -1, i2 = array.length,
          o ;
    
        while(++i1 < i2)
        {
            o = array[i1] ; // you have to use the bracket operator here
            if(o.hasOwnProperty(key)) a[a.length] = o[key] ;
        }
      return a ;
    }
    

    I didn’t really change all that much. The reason why your code failed is because you used the dot operator .key to access the named property of the array elements instead of the bracket operator [key]. When using a reference as a key you need to use the bracket operator.

    Login or Signup to reply.
  4. How about a reduce:

    $.pluck = function(arr, key) { 
        return arr.reduce(function(p, v) { 
          return p.concat(v[key]); 
        }, []); 
    }
    
    var people = [
      { name: 'James', age: 26 }, 
      { name: 'Fred', age: 56 }
    ];
    
    $.pluck(people, 'age');
    => [26, 56]
    
    $.pluck(people, 'name');
    => ['James', 'Fred']
    
    Login or Signup to reply.
  5. In ES5:

    function pluck(array, key) {
      return array.map(function(obj) {
        return obj[key];
      });
    }
    

    In ES6:

    function pluck(array, key) {
      return array.map(o => o[key]);
    }
    
    Login or Signup to reply.
  6. var array = {
    name: ["Pedro", "João", "Francisco", "Diogo"],
    ID: [1,2,3,4]
    };
    console.log(pluck(array,'name'));
    
    function pluck(array, key) {
       return (array[key]);
    };
    

    JSFiddle

    You can use this function, click in JSFiddle to see a Example!! 🙂

    Login or Signup to reply.
  7. Here’s an example of doing _.pluck(Tuts, 'name');

    const Tuts = [{name : 'NetTuts', niche : 'Web Development'}, {name : 'WPTuts', niche : 'WordPress'}, {name : 'PSDTuts', niche : 'PhotoShop'}, {name : 'AeTuts', niche : 'After Effects'}];
    
    
    const pluckedNames = Tuts.map(({ name }) => name);
    

    If you want to remove the undefined values in the case that there is no name in the object, you can use a .filter() afterward

    const pluckedNames = Tuts.map(({ name }) => name).filter(i => i);
    
    Login or Signup to reply.
  8. How about using Proxy?

    f = new Proxy(x => x, {
        get: (_,prop) => x => x[prop]
    })
    

    Here’s an example of doing _.pluck(Tuts, ‘name’);

    const Tuts = [{name : 'NetTuts', niche : 'Web Development'}, {name : 'WPTuts', niche : 'WordPress'}, {name : 'PSDTuts', niche : 'PhotoShop'}, {name : 'AeTuts', niche : 'After Effects'}];
    const pluckedNames = Tuts.map(f.name);
    

    If you want to remove the undefined values in the case that there is no name in the object, you can use a .filter() afterward

    const pluckedNames = Tuts.map(f.name).filter(f);
    
    Login or Signup to reply.
  9. Just plain simple without the need to use methods:

    var pluck = function (arr, key) {
      var newArr = [];
      for (let i = 0; i < arr.length; i++) {
        newArr.push(arr[i][key]);
      }
      return newArr;
    };
    Login or Signup to reply.
  10. This is combined function for some cases when you need an object with key value:

    const pluck = (array, value, key = null) => {
        const newArray = key ? {} : [];
    
        array.forEach((item) => {
            if (key) {
                newArray[item[key]] = item[value];
            } else {
                newArray.push(item[value]);
            }
        });
    
        return newArray;
    }
    

    Example:

    const a = [
        {key1: 'value1', key2: 'value2'}, 
        {key1: 'value3', key2: 'value4'},
    ];
    const result = pluck(a, 'key2', 'key1');
    

    It will return:

    {value1: 'value2', value3: 'value4'}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search