Collecting and merging JavaScript arrays

I have a dataset that looks like this:

[
    {
        ProductID: 1,
        ProductName: 'MyProduct',
        Description: '.. some text here ..',
        UnwantedData: 'garbage here'
    },
    {
        ProductID: 2,
        ProductName: 'MyOtherProduct',
        Description: '.. some text here ..',
        UnwantedData: 'garbage herAe',
        GarbageField: '.. lorem ipsum ..'
    }
]

      

I also have a reference array that looks like this:

[
    {
        name: 'ProductId',
        map_to: 'item_id',
    },
    {
        name: 'ProductName',
        map_to: 'item_name',
    },
    {
        name: 'Description',
        map_to: 'description',
    },
]

      

What I want to do is use this referenced array to basically discard the "unwanted" data (ie properties that are not name

in the referenced array) and replace the keys with whatever it should have displayed on (ie . ProductId->item_id

).

The resulting array should look like this:

[
    {
        item_id: 1,
        item_name: 'MyProduct',
        description: '.. some text here ..'
    },
    {
        item_id: 2,
        item_name: 'MyOtherProduct',
        description: '.. some text here ..'
    }
]

      

What have I done so far

Considering what ref

is a reference array and data

is a list of products.

var only = _.map( ref, 'name' );
var products = [];

async.eachLimit( data, 20, function(item, cb) {

    products.push( _.pick(item, only) );
    cb();
}, function(err) {

    // .. then I iterate over the products array and manually replace each property 
    // I haven't done this yet
});

      

This code should work, but it feels a little inefficient and I want to know if there is a better way to achieve the desired resulting array as I am going to store them in MongoDB.

Can anyone shed some light here?

+3


source to share


3 answers


You can try for

loops:

var result = [];
for(var i=0; i<data.length; ++i) {
  result[i] = {};
  for(var j=0; j<ref.length; ++j)
    result[i][ref[j].map_to] = data[i][ref[j].name];   
}

      

var data = [
  {
    ProductID: 1,
    ProductName: 'MyProduct',
    Description: '.. some text here ..',
    UnwantedData: 'garbage here'
  }, {
    ProductID: 2,
    ProductName: 'MyOtherProduct',
    Description: '.. some text here ..',
    UnwantedData: 'garbage herAe',
    GarbageField: '.. lorem ipsum ..'
  }
];
var ref = [
  {
    name: 'ProductID',
    map_to: 'item_id',
  }, {
    name: 'ProductName',
    map_to: 'item_name',
  }, {
    name: 'Description',
    map_to: 'description',
  },
];
var result = [];
for(var i=0; i<data.length; ++i) {
  result[i] = {};
  for(var j=0; j<ref.length; ++j)
    result[i][ref[j].map_to] = data[i][ref[j].name];   
}
console.log(result);
      

Run codeHide result




Or, using ES5 array methods,

data.map(function(old) {
  return ref.reduce(function(obj, assoc) {
    obj[assoc.map_to] = old[assoc.name];
    return obj;
  }, {});
});

      

var data = [
  {
    ProductID: 1,
    ProductName: 'MyProduct',
    Description: '.. some text here ..',
    UnwantedData: 'garbage here'
  }, {
    ProductID: 2,
    ProductName: 'MyOtherProduct',
    Description: '.. some text here ..',
    UnwantedData: 'garbage herAe',
    GarbageField: '.. lorem ipsum ..'
  }
];
var ref = [
  {
    name: 'ProductID',
    map_to: 'item_id',
  }, {
    name: 'ProductName',
    map_to: 'item_name',
  }, {
    name: 'Description',
    map_to: 'description',
  },
];
console.log(data.map(function(old) {
  return ref.reduce(function(obj, assoc) {
    obj[assoc.map_to] = old[assoc.name];
    return obj;
  }, {});
}));
      

Run codeHide result


+2


source


I usually find it easier to pair objects with _.pairs

, work in pairs, and then cast them back into the object with _.object

:

function goodPair(product_pair) {
    var k = product_pair[0];
    return refmap[k] != null;
}

function fixPair(product_pair) {
    var k = product_pair[0];
    var v = product_pair[1];
    return [refmap[k], v];
}

function trimProduct(full_product) {
    return _.object(_.pairs(full_product)
        .filter(goodPair)
        .map(fixPair));
}

console.log(data.map(trimProduct));

      

This way you can turn the whole transformation into one synchronous map

across your product array.



Note that this is a slightly simplified version of your ref

here asrefmap

var refmap = _.object(ref.map(function(r) {
    return [r.name, r.map_to];
}));

// OR

var refmap = {
    'ProductId': 'item_id',
    'ProductName': 'item_name',
    'Description': 'description',
};

      

+2


source


I would use map () and transform () for this:

_.map(data, function(item) {
    return _.transform(ref, function(result, r) {
        result[r.map_to] = item[r.name];
    }, {});
});

      

You map yours data

to the new structure. Each new element is the result of a transformation of the element ref

. The key map_to

in the new object gets the value name

in the original collection.

+1


source







All Articles