Reproducing MongoDB's map/emit functionality in javascript/node.js (without MongoDB) - javascript

I like the functionality that MongoDB provides for doing map/reduce tasks, specifically the emit() in the mapper function. How can I reproduce the map behavior shown below in javascript/node.js without MongoDB?
Example (from MongoDB Map-Reduce Docs):
[{ cust_id: "A123", amount: 500 }, { cust_id: "A123", amount: 250 }, { cust_id: "B212", amount: 200 }]
Mapped to -
[{ "A123": [500, 200] }, { "B212": 200 }]
A library that makes it as simple as Mongo's one line emit() would be nice but native functions would do the job as well.

Array.reduce does what you need.
here is documentation: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
I also suggest you to use undescore.js (as in first comment) which has reduce & reduceRight.
http://underscorejs.org/#reduce

If you just neeed to have the emit syntax, it's possible. Scan out the function body and pass in a new emit function.
function mapReduce(docs, m, r) {
var groups = {}
function emit(key, value) {
if (!groups[key]) { groups[key] = [] }
groups[key].push(value)
}
var fn = m.toString()
var body = fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
var map = new Function('emit', body)
docs.forEach(function (doc) {
map.call(doc, emit)
})
var outs = []
Object.keys(groups).forEach(function (key) {
outs.push({ _id: key, value: r(key, groups[key]) })
})
return outs
}
Edit, forgot example:
var docs = // from above
Array.sum = function (values) {
return values.reduce(function (a, b) { return a + b })
}
mapReduce(docs,
function () {
emit(this.cust_id, this.amount)
},
function (k, values) {
return Array.sum(values)
}
)
// [ { _id: 'A123', value: 750 }, { _id: 'B212', value: 200 } ]

I agree that there are lots of great lib ways to do this, and it's simple to do with Array methods. Here is a fiddle with my suggestion. It's pretty simple, and just uses the forEach Array method. I've done it in a single loop, but there are many other ways.
I haven't done the reduce at the end, as you didn't ask for that, but I hope this helps.
function emit (key, value, data) {
var res = {}; out = [];
data.forEach(function (item) {
var k = item[key];
var v = item[value];
if (k !== undefined && v !== undefined) {
if (res[k] !== undefined) {
out[res[k]][k].push(v);
} else {
var obj = {};
res[k] = out.length;
obj[k] = [v];
out.push(obj);
}
}
});
return out;
}
var data = [{name: 'Steve', amount: 50},{name: 'Steve', amount: 400}, {name: 'Jim', amount: 400}];
emit('name', 'amount', data)) // returns [{"Steve":[50,400]},{"Jim":[400]}]
emit('amount', 'name', data)) // returns [{"50":["Steve"]},{"400":["Steve","Jim"]}]
I've used an object to store the array index for each unique entry. There are lots of versions of this. Probably many better than mine, but thought I'd give you a vanilla JS version.

Related

Removing duplicates with in an object array using angular 4

I have an array with below list of items as shown in image , I would like to remove the duplicates
[L7-LO, %L7-LO] from that array.
I have tried with the following conditions:
Scenario 1 :
this.formulalist.filter((el, i, a) => i == a.indexOf(el))
Scenario 2:
Observable.merge(this.formulalist).distinct((x) => x.Value)
.subscribe(y => {
this.formulalist.push(y)
});
Scenario 3:
this.formulalist.forEach((item, index) => {
if (index !== this.formulalist.findIndex(i => i.Value == item.Value))
{
this.formulalist.splice(index, 1);
}
});
None of the three scenarios above were able to remove the duplicates from that array. Could any one please help on this query?
angular is not necessary use vanillajs
filter the elements with only one occurrence and add to the new list the first occurrence
let newFormulalist = formulalist.filter((v,i) => formulalist.findIndex(item => item.value == v.value) === i);
Try populating a new array without duplicates. Assign the new array later to formulalist.
newArr = []
this.formulalist.forEach((item, index) => {
if (this.newArr.findIndex(i => i.Value == item.Value) === -1)
{
this.newArr.push(item)
}
});
this.formulalist = this.newArr
EDIT
Looking at the answer above, the solution seems so outdated. A better approach would have been to use an Array.filter() than a Array.forEach().
But, having a better solution would be nice, now when I see this question, I feel findIndex() not to be a good approach because of the extra traversal.
I may have a Set and store the values in the Set on which I want to filter, If the Set has those entries, I would skip those elements from the array.
Or a nicer approach is the one that is used by Akitha_MJ, very concise. One loop for the array length, an Object(Map) in the loop with keys being the value on which we want to remove duplicates and the values being the full Object(Array element) itself. On the repetition of the element in the loop, the element would be simply replaced in the Map. Later just take out the values from the Map.
const result = Array.from(this.item.reduce((m, t) => m.set(t.name, t), new Map()).values());
Hope this works !!
// user reduce method to remove duplicates from object array , very easily
this.formulalist= this.formulalist.reduce((a, b) => {
if (!a.find(data => data.name === b.name)) {
a.push(b);
}
return a;
}, []);
// o/p = in formulalist you will find only unique values
Use a reducer returning a new array of the unique objects:
const input = [{
value: 'L7-LO',
name: 'L7-LO'
},
{
value: '%L7-LO',
name: '%L7-LO'
},
{
value: 'L7-LO',
name: 'L7-LO'
},
{
value: '%L7-LO',
name: '%L7-LO'
},
{
value: 'L7-L3',
name: 'L7-L3'
},
{
value: '%L7-L3',
name: '%L7-L3'
},
{
value: 'LO-L3',
name: 'LO-L3'
},
{
value: '%LO-L3',
name: '%LO-L3'
}
];
console.log(input.reduce((acc, val) => {
if (!acc.find(el => el.value === val.value)) {
acc.push(val);
}
return acc;
}, []));
if you are working using ES6 and up, basic JS using map and filter functions makes it easy.
var array = [{value:"a"},{value:"b"},{value:"c"},{value:"a"},{value:"c"},{value:"d"}];
console.log(array.filter((obj, pos, arr) => {
return arr.map(mapObj => mapObj["value"]).indexOf(obj["value"]) === pos;
}));
Filtering for unique values is much faster with assigning values to some object properties - there not will be duplicates.
This approach gets better and better with every +1 member of initial array, because looping will be causing fast algorithm complications
let arr = [
{value: 'L7-LO', name: 'L7-LO'},
{value: '%L7-LO', name: '%L7-LO'},
{value: 'L7-LO', name: 'L7-LO'},
{value: '%L7-LO', name: '%L7-LO'},
{value: 'L7-L3', name: 'L7-L3'},
{value: '%L7-L3', name: '%L7-L3'},
{value: 'LO-L3', name: 'LO-L3'},
{value: '%LO-L3', name: '%LO-L3'}
];
let obj = {};
const unique = () => {
let result = [];
arr.forEach((item, i) => {
obj[item['value']] = i;
});
for (let key in obj) {
let index = obj[key];
result.push(arr[index])
}
return result;
}
arr = unique(); // for example;
console.log(arr);

Turn array of comma delimited strings into distinct array

I would like to take an array of objects:
var objArr = [
{id:1, name:'test', seenby:'user1, user2, user3'},
{id:2, name:'test1', seenby:'user3, user4'},
{id:3, name:'test2', seenby:'user1, user3'},
{id:4, name:'test3', seenby:'user2'}
];
And return a distinct array of all 'seenby' users:
var seenByArr = ['user1', 'user2', 'user3', 'user4']
I can't figure out how to efficiently (fewest lines possible) turn this into an array of distinct values. Please check out my fiddle for an example: https://jsfiddle.net/ksumarine/ss3v7dgj/
I realize this question doesn't mention Underscore, but it's worth mentioning that Underscore.js is a very popular library for manipulating objects and arrays, and well-suited for this kind of thing.
Here's a big unreadable single line for achieving this with Underscore:
_.unique(_.flatten(_.map(_.pluck(objArr, 'seenby'), function(seenby) { return seenby.split(', '); })))
The laconic solution with String.split and Array.foreach functions:
var arr = [];
objArr.forEach(function (obj) {
var str = obj.seenby.split(',');
str.forEach(function (v) {
var user = v.trim();
if (arr.indexOf(user) === -1) arr.push(user);
});
});
console.log(arr);
// the output:
["user1", "user2", "user3", "user4"]
You can try following
$.each(list, function(index, value) {
$.each(value.seenby.split(","), function(i, val) {
if (val !== undefined && val.trim() !== "" && arr.indexOf(val.trim()) == -1) {
arr.push(val.trim());
}
});
});
For reference - https://jsfiddle.net/ss3v7dgj/1/
A solution in plain Javascript with an IIFE and a temporary object for the items.
var objArr = [{ id: 1, name: 'test', seenby: 'user1, user2, user3' }, { id: 2, name: 'test1', seenby: 'user3, user4' }, { id: 3, name: 'test2', seenby: 'user1, user3' }, { id: 4, name: 'test3', seenby: 'user2' }],
result = function (array) {
var obj = {}, r = [];
array.forEach(function (a) {
a.seenby.split(', ').forEach(function (b) {
obj[b] = obj[b] || r.push(b);
});
});
return r;
}(objArr);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
given = function (x) {
return {
do: function (f) { x = f(x); return this },
return: function () { return x }
}
};
r = given(objArr)
.do(x => x.map(y => y.seenby))
.do(x => [].concat.apply([], x))
.do(x => x.join(', '))
.do(x => x.split(', '))
.do(x => x.filter((e, i) => x.indexOf(e) === i))
.do(x => x.sort())
.return();
I might find use for this someday...
I would use the Array.prototype.map function, and de-duplicate the users in a associative array. So here the interesting part, but you can also try it out here:
var list = [
{id:1, name:'test', seenby:'user1, user2, user3'},
{id:2, name:'test1', seenby:'user3, user4'},
{id:3, name:'test2', seenby:'user1, user3'},
{id:4, name:'test3', seenby:'user2'}
];
var arr = [];
list.map(function(value){
value.seenby.split(",").map(function(val){
arr[val.trim()] = 1;
});
});
var seenby = Object.keys(arr);
How does it work? The map function will iterate over all the list items, the next map will iterate over all the seenby items. We then collect the users in the arr, de-duplicating by using it as an associative array.
At the end we extract all the associative array keys by using the Object.keys function.
Minor caveat is that this solution will only work if the map function exists, if it doesn't you would need to implement it yourself. But usually you are using a new enough JavaScript version that does support it. This solution also has the nice side effect that you don't really need any external dependency (except of course for displaying it)
UPDATE:
I think it's actually better to do it the following way:
var arr = list
.reduce(function(acc, value){
return acc.concat(value.seenby.split(",").map(function(val){
return val.trim()
}))},[])
.filter(function(item, index, array) {
return array.indexOf(item) === index
}
)
Explanation:
we take the list and for each item, we reduce it ...
from each item, we extract the seenby field
we split the field
we map each item to trim it
... we take the array of returned seenby and concatenate them to our accumulator array arr (which is initialized as empty array [])
then we filter out the duplicates from the array (by checking whether the index of an item is the same as the current index)

How to use lodash to find and return an object from Array?

My objects:
[
{
description: 'object1', id: 1
},
{
description: 'object2', id: 2
}
{
description: 'object3', id: 3
}
{
description: 'object4', id: 4
}
]
In my function below I'm passing in the description to find the matching ID:
function pluckSavedView(action, view) {
console.log('action: ', action);
console.log('pluckSavedView: ', view); // view = 'object1'
var savedViews = retrieveSavedViews();
console.log('savedViews: ', savedViews);
if (action === 'delete') {
var delete_id = _.result(_.find(savedViews, function(description) {
return description === view;
}), 'id');
console.log('delete_id: ', delete_id); // should be '1', but is undefined
}
}
I'm trying to use lodash's find method: https://lodash.com/docs#find
However my variable delete_id is coming out undefined.
Update for people checking this question out, Ramda is a nice library to do the same thing lodash does, but in a more functional programming way :)
http://ramdajs.com/0.21.0/docs/
lodash and ES5
var song = _.find(songs, {id:id});
lodash and ES6
let song = _.find(songs, {id});
docs at https://lodash.com/docs#find
The argument passed to the callback is one of the elements of the array. The elements of your array are objects of the form {description: ..., id: ...}.
var delete_id = _.result(_.find(savedViews, function(obj) {
return obj.description === view;
}), 'id');
Yet another alternative from the docs you linked to (lodash v3):
_.find(savedViews, 'description', view);
Lodash v4:
_.find(savedViews, ['description', view]);
You can do this easily in vanilla JS:
Using find:
const savedViews = [{"description":"object1","id":1},{"description":"object2","id":2},{"description":"object3","id":3},{"description":"object4","id":4}];
const view = 'object2';
const delete_id = savedViews.find(obj => {
return obj.description === view;
}).id;
console.log(delete_id);
Using filter (original answer):
const savedViews = [{"description":"object1","id":1},{"description":"object2","id":2},{"description":"object3","id":3},{"description":"object4","id":4}];
const view = 'object2';
const delete_id = savedViews.filter(function (el) {
return el.description === view;
})[0].id;
console.log(delete_id);
With the find method, your callback is going to be passed the value of each element, like:
{
description: 'object1', id: 1
}
Thus, you want code like:
_.find(savedViews, function(o) {
return o.description === view;
})
You don't need Lodash or Ramda or any other extra dependency.
Just use the ES6 find() function in a functional way:
savedViews.find(el => el.description === view)
Sometimes you need to use 3rd-party libraries to get all the goodies that come with them. However, generally speaking, try avoiding dependencies when you don't need them. Dependencies can:
bloat your bundled code size,
you will have to keep them up to date,
and they can introduce bugs or security risks
for this find the given Object in an Array, a basic usage example of _.find
const array =
[
{
description: 'object1', id: 1
},
{
description: 'object2', id: 2
},
{
description: 'object3', id: 3
},
{
description: 'object4', id: 4
}
];
this would work well
q = _.find(array, {id:'4'}); // delete id
console.log(q); // {description: 'object4', id: 4}
_.find will help with returning an element in an array, rather than it’s index. So if you have an array of objects and you want to find a single object in the array by a certain key value pare _.find is the right tools for the job.
Import lodash using
$ npm i --save lodash
var _ = require('lodash');
var objArrayList =
[
{ name: "user1"},
{ name: "user2"},
{ name: "user2"}
];
var Obj = _.find(objArrayList, { name: "user2" });
// Obj ==> { name: "user2"}
You can use the following
import { find } from 'lodash'
Then to return the entire object (not only its key or value) from the list with the following:
let match = find(savedViews, { 'ID': 'id to match'});
var delete_id = _(savedViews).where({ description : view }).get('0.id')
Fetch id basing on name
{
"roles": [
{
"id": 1,
"name": "admin",
},
{
"id": 3,
"name": "manager",
}
]
}
fetchIdBasingOnRole() {
const self = this;
if (this.employee.roles) {
var roleid = _.result(
_.find(this.getRoles, function(obj) {
return obj.name === self.employee.roles;
}),
"id"
);
}
return roleid;
},

Build a JSON object from absolute filepaths

I receive (in my angularjs application) from a server a list of directories like this:
['.trash-user',
'cats',
'cats/css',
'cats/images/blog',
'cats/images/gallery']
And I would like to build a javascript variable which looks like this:
[{
label: '.trash-user'},
{label: 'cats',
children: [{
label: 'css'},
{label: 'images',
children: [{
label: 'blog'},
{label: 'gallery'}
]}
]}
}]
The paths are in random order.
Hope somebody has some really elegant solution, but any solution is appreciated!
Edit:
Here is my naive approach, I have real trouble with recursion.
I could only make level 0 to work:
var generateTree = function(filetree){
console.log('--------- filetree -------');
var model = [];
var paths = [];
for(var i=0;i<filetree.length;i++) {
paths = filetree[i].split('/');
for(var j=0;j<paths.length;++j) {
var property = false;
for(var k=0;k<model.length;++k) {
if (model[k].hasOwnProperty('label') &&
model[k].label === paths[0]) {
property = true;
}
}
if (!property) {
model.push({label: paths[0]});
}
}
}
console.log(model);
};
If you want an elegant solution, lets start with a more elegant output:
{
'.trash-user': {},
'cats': {
'css': {},
'images': {
'blog': {},
'gallery': {},
},
},
}
Objects are much better than arrays for storing unique keys and much faster too (order 1 instead of order n). To get the above output, do:
var obj = {};
src.forEach(p => p.split('/').reduce((o,name) => o[name] = o[name] || {}, obj));
or in pre-ES6 JavaScript:
var obj = {};
src.forEach(function(p) {
return p.split('/').reduce(function(o,name) {
return o[name] = o[name] || {};
}, obj);
});
Now you have a natural object tree which can easily be mapped to anything you want. For your desired output, do:
var convert = obj => Object.keys(obj).map(key => Object.keys(obj[key]).length?
{ label: key, children: convert(obj[key]) } : { label: key });
var arr = convert(obj);
or in pre-ES6 JavaScript:
function convert(obj) {
return Object.keys(obj).map(function(key) {
return Object.keys(obj[key]).length?
{ label: key, children: convert(obj[key])} : { label: key };
});
}
var arr = convert(obj);
I'll venture that generating the natural tree first and then converting to the array will scale better than any algorithm working on arrays directly, because of the faster look-up and the natural impedance match between objects and file trees.
JSFiddles: ES6 (e.g. Firefox), non-ES6.
Something like this should work:
function pathsToObject(paths) {
var result = [ ];
// Iterate through the original list, spliting up each path
// and passing it to our recursive processing function
paths.forEach(function(path) {
path = path.split('/');
buildFromSegments(result, path);
});
return result;
// Processes each path recursively, one segment at a time
function buildFromSegments(scope, pathSegments) {
// Remove the first segment from the path
var current = pathSegments.shift();
// See if that segment already exists in the current scope
var found = findInScope(scope, current);
// If we did not find a match, create the new object for
// this path segment
if (! found) {
scope.push(found = {
label: current
});
}
// If there are still path segments left, we need to create
// a children array (if we haven't already) and recurse further
if (pathSegments.length) {
found.children = found.children || [ ];
buildFromSegments(found.children, pathSegments);
}
}
// Attempts to find a ptah segment in the current scope
function findInScope(scope, find) {
for (var i = 0; i < scope.length; i++) {
if (scope[i].label === find) {
return scope[i];
}
}
}
}

Efficiently rename/re-map javascript/json object keys within array of objects

I have some structured JSON data like so. Let's assume this is interchangeable, via JSON.parse():
[
{
"title": "pineapple",
"uid": "ab982d34c98f"
},
{
"title": "carrots",
"uid": "6f12e6ba45ec"
}
]
I need it to look like this, remapping title to name, and uid to id with the result:
[
{
"name": "pineapple",
"id": "ab982d34c98f"
},
{
"name": "carrots",
"id": "6f12e6ba45ec"
}
]
The most obvious way of doing it is like this:
str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]';
var arr = JSON.parse(str);
for (var i = 0; i<arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
str = '[{"title": "pineapple","uid": "ab982d34c98f"},{"title": "carrots", "uid": "6f12e6ba45ec"}]';
var arr = JSON.parse(str);
for (var i = 0; i<arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
$('body').append("<pre>"+JSON.stringify(arr, undefined, 4)+"</pre>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
...or using something more complex (albeit not more efficient) like this.
This is all fine and dandy, but what if there were 200,000 objects in the array? This is a lot of processing overhead.
Is there a more efficient way to remap a key name? Possibly without looping through the entire array of objects? If your method is more efficient, please provide proof/references.
As I already mentioned in the comments, if you can make certain assumptions about the values of the objects, you could use a regular expression to replace the keys, for example:
str = str.replace(/"title":/g, '"name":');
It's not as "clean", but it might get the job done faster.
If you have to parse the JSON anyway, a more structured approach would be to pass a reviver function to JSON.parse and you might be able to avoid an additional pass over the array. This probably depends on how engine implement JSON.parse though (maybe they parse the whole string first and then make a second pass with the reviver function, in which case you wouldn't get any advantage).
var arr = JSON.parse(str, function(prop, value) {
switch(prop) {
case "title":
this.name = value;
return;
case "uid":
this.id = value;
return;
default:
return value;
}
});
Benchmarks, using the Node.js script below to test 3 times:
1389822740739: Beginning regex rename test
1389822740761: Regex rename complete
// 22ms, 22ms, 21ms
1389822740762: Beginning parse and remap in for loop test
1389822740831: For loop remap complete
// 69ms, 68ms, 68ms
1389822740831: Beginning reviver function test
1389822740893: Reviver function complete
// 62ms, 61ms, 60ms
It appears as if the regex (in this case) is the most efficient, but be careful when trying to parse JSON with regular expressions.
Test script, loading 100,230 lines of the OP's sample JSON:
fs = require('fs');
fs.readFile('test.json', 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
console.log(new Date().getTime() + ": Beginning regex rename test");
var str = data.replace(/"title":/g, '"name":');
str = str.replace(/"uid":/g, '"id":');
JSON.parse(str);
console.log(new Date().getTime() + ": Regex rename complete");
console.log(new Date().getTime() + ": Beginning parse and remap in for loop test");
var arr = JSON.parse(data);
for (var i = 0; i < arr.length; i++) {
arr[i].name = arr[i].title;
arr[i].id = arr[i].uid;
delete arr[i].title;
delete arr[i].uid;
}
console.log(new Date().getTime() + ": For loop remap complete");
console.log(new Date().getTime() + ": Beginning reviver function test");
var arr = JSON.parse(data, function (prop, value) {
switch (prop) {
case "title":
this.name = value;
return;
case "uid":
this.id = value;
return;
default:
return value;
}
});
console.log(new Date().getTime() + ": Reviver function complete");
});
Asked this question a long time ago, and since then, I've grown acustomed to using Array.prototype.map() to get the job done, more for stability and cleanliness of code than performance. While it's certainly not the most performant, it looks great:
var repl = orig.map(function(obj) {
return {
name: obj.title,
id: obj.uid
}
})
If you need a more flexible (and ES6-compatible function), try:
let replaceKeyInObjectArray = (a, r) => a.map(o =>
Object.keys(o).map((key) => ({ [r[key] || key] : o[key] })
).reduce((a, b) => Object.assign({}, a, b)))
e.g.
const arr = [{ abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }, { abc: 1, def: 40, xyz: 50 }]
const replaceMap = { "abc": "yyj" }
replaceKeyInObjectArray(arr, replaceMap)
/*
[
{
"yyj": 1,
"def": 40,
"xyz": 50
},
{
"yyj": 1,
"def": 40,
"xyz": 50
},
{
"yyj": 1,
"def": 40,
"xyz": 50
}
]
*/
Here's another take on the OP's suggestion to use map() for clarity (not performance).
var newItems = items.map(item => ({
name: item.title,
id: item.uid
}));
This uses ES6 arrow functions and the shortcut syntaxes that are possible when there's only one parm passed to the function and only one statement in the body of the function.
Depending on your history with lambda expressions in various languages, this form may or may not resonate with you.
Be careful when returning an object literal in the arrow function shortcut syntax like this. Don't forget the additional parens around the object literal!
If you want to make it a little more reusable. Maybe this is a decent approach.
function rekey(arr, lookup) {
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
for (var fromKey in lookup) {
var toKey = lookup[fromKey];
var value = obj[fromKey];
if (value) {
obj[toKey] = value;
delete obj[fromKey];
}
}
}
return arr;
}
var arr = [{ apple: 'bar' }, { apple: 'foo' }];
var converted = rekey(arr, { apple: 'kung' });
console.log(converted);
Using ES6:
const renameFieldInArrayOfObjects = (arr, oldField, newField) => {
return arr.map(s => {
return Object.keys(s).reduce((prev, next) => {
if(next === oldField) {
prev[newField] = s[next]
} else {
prev[next] = s[next]
}
return prev
}, {})
})
}
Using ES7:
const renameFieldInArrayOfObjects = (arr, oldField, newField) => {
return arr.map(s => {
return Object.keys(s).reduce((prev, next) => {
return next === oldField
? {...prev, [newField]: s[next]}
: {...prev, [next]: s[next]}
}, {})
})
}
You can use an npm package named node-data-transform.
Your data :
const data = [
{
title: 'pineapple',
uid: 'ab982d34c98f',
},
{
title: 'carrots',
uid: '6f12e6ba45ec',
},
];
Your mapping :
const map = {
item: {
name: 'title',
id: 'uid',
},
};
And use the package :
const DataTransform = require("node-json-transform").DataTransform;
const dataTransform = DataTransform(data, map);
const result = dataTransform.transform();
console.log(result);
Result :
[
{
name: 'pineapple',
id: 'ab982d34c98f'
},
{
name: 'carrots',
id: '6f12e6ba45ec'
}
]
Maybe it's not the best way for performance, but it's quite elegant.
var jsonObj = [/*sample array in question*/ ]
Based on different benchmarks discussed below, fastest solution is native for:
var arr = [];
for(var i = 0, len = jsonObj .length; i < len; i++) {
arr.push( {"name": jsonObj[i].title, "id" : jsonObj[i].uid});
}
I think alternatively without using a frameworks this will be option 2:
var arr = []
jsonObj.forEach(function(item) { arr.push({"name": item.title, "id" : item.uid }); });
There is always debate between using navite and non-navite functions. If I remember correctly lodash argued they were faster than underscore because the use non-native functions for key operations.
However different browsers will produce sometimes very different results. I always looked for the best average.
For benchmarks you can take a look at this:
http://jsperf.com/lo-dash-v1-1-1-vs-underscore-v1-4-4/8
function replaceElem(value, replace, str) {
while (str.indexOf(value) > -1) {
str = str.replace(value, replace);
}
return str;
}
call this from main
var value = "tittle";
var replace = "name";
replaceElem(value, replace, str);

Categories

Resources