lodash map returning array of objects - javascript

i have a arrray of objects where i wish to convert the data from medicine to type string. The only problem is instead of returning the array of objects is returing me the array of medicine.
Example
input:
data = [{medicine: 1234, info: "blabla"},{medicine: 9585, info: "blabla"},..]
desired output:
data = [{medicine: "1234", info: "blabla"},{medicine: "9585", info: "blabla"},..]
What im getting?
Array of medicine numbers.
Here is my code:
var dataMedicines = _.map(data, 'medicine').map(function(x) {
return typeof x == 'number' ? String(x) : x;
});

Lodash is much powerful, but for simplicity, check this demo
var data = [{
medicine: 1234,
info: "blabla"
}, {
medicine: 9585,
info: "blabla"
}];
dataMedicines = _.map(data, function(x) {
return _.assign(x, {
medicine: x.medicine.toString()
});
});
console.log(dataMedicines);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script>

Or just a native ES6 solution:
const dataMedicines = data.map(({medicine, info}) => ({medicine: `${medicine}`, info}));
The advantage is that this is a more functional solution that leaves the original data intact.

I'm guessing you want "transform" all medicine number to strings?
If that's the case, you don't need to first map.
var dataMedicines = _.map(data, function(x){
var newObj = JSON.parse(JSON.stringify(x)); // Create a copy so you don't mutate the original.
newObj.medicine = newObj.medicine.toString(); // Convert medicine to string.
return newObj;
});

Related

How to do mapping for two objects and array in javascript

I have such a object and array which I received response from my server. I need to convert that to second format at below in order to print the value in the website. Is this something need to do object mapping? or parse JSON or please kindly help.
{"header":["SEOUL","BUSAN","NAMPODONG"],"data":[[38,"CAPITAL","M31"]]},
Convert from Above to below
'{"SEOUL" : "38", "BUSAN" : "CAPITAL", "NAMPODONG" : "M31"}'
var finalObj = {};
response.header.forEach(function(item, index) {
finalObj[item] = response.data[0][index];
});
Above code is working fine as it create variable and loop for header and get its value and printed in html. the header and data are from the server so when I enter something let say "A" then it will look for SEOUL header then print 38 in html as tables are looks below.
key value : A
header : SEOUL BUSAN NAMPODONG
data : 38 CAPITAL M31
I do have a lot of data in the database, above is just an example. So let say I enter B then the B is not in database so I want to see the value "No found" in html but this code printing nothing so not sure whether it was proceed or not.
Create a variable & loop over the object.header to get each key and object.data[0] to get its value
var myObj = {
"header": ["SEOUL", "BUSAN", "NAMPODONG"],
"data": [
[38, "CAPITAL", "M31"]
]
}
var tempObj = {};
myObj.header.forEach(function(item, index) {
tempObj[item] = myObj.data[0][index]
})
console.log(tempObj)
As you received it from server – I assume that it is JSON string.
Basically you have two arrays here that you want to reduce to an object.
So I would do it like this:
const object = JSON.parse('{"header":["SEOUL","BUSAN","NAMPODONG"],"data":[[38,"CAPITAL","M31"]]}');
const result = object.header.reduce(function(accumulator, element, i){
accumulator[element] = object.data[0][i] // You had nested array here so I have to get first element.
return accumulator;
}, {});
console.log(result);
I assumed that nested array for data attribute is some kind of formatting mistake. If it's not – you have to map though it's elements first and only then reduce.
You can use zipObj from Ramda library.
The code would look like this:
const res = {"header":["SEOUL","BUSAN","NAMPODONG"],"data":[[38,"CAPITAL","M31"]]}
const obj = R.zipObj(res.header, res.data[0])
console.log(obj)
<script src="//cdn.jsdelivr.net/npm/ramda#latest/dist/ramda.min.js"></script>
You could map the new objects with the wanted keys.
The result is an array with objects, because your data is a nested array with actually only one array. But it looks like taht data could contain more than one row.
var data = { header: ["SEOUL", "BUSAN", "NAMPODONG"], data: [[38, "CAPITAL", "M31"]] },
result = data.data.map(a => Object.assign(...data.header.map((k, i) => ({ [k]: a[i] }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can map the data array of arrays into another array of object using as keys the strings in header array:
function transform(obj) {
return obj.data.map(function(subArray) { // for each subArray in the data array
return subArray.reduce(function(o, val, i) { // create a new object o which...
o[ obj.header[i] ] = val; // has key-value pairs where value is the current element of subArray and key is its equivalent (item at the same index) from header array
return o;
}, {});
});
}
var obj = {"header":["SEOUL","BUSAN","NAMPODONG"],"data":[[38,"CAPITAL","M31"], [10,"OTHER","M01"]]};
var result = transform(obj);
console.log(result);
I think the responses above are good as they are, but here is an alternative using reduce in case you didn't know about it
var response = {
"header": ["SEOUL", "BUSAN", "NAMPODONG"],
"data": [
[38, "CAPITAL", "M31"]
]
};
var result = response.header.reduce(function(accum, v, i) {
accum[v] = response.data[0][i];
return accum;
}, {})
console.log(result)

JavaScript - Filter <key,value> Object by key

I am looking for a short and efficient way to filter objects by key, I have this kind of data-structure:
{"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]}
Now I want to filter by keys, for example by "Key1":
{"Key1":[obj1,obj2,obj3]}
var object = {"Key1":[1,2,3], "Key2":[4,5,6]};
var key1 = object["Key1"];
console.log(key1);
you can use the .filter js function for filter values inside an object
var keys = {"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]};
var objectToFind;
var keyToSearch = keys.filter(function(objects) {
return objects === objectToFind
});
The keyToSearch is an array with all the objects filter by the objectToFind variable.
Remember, in the line return objects === objectToFind is where you have to should your statement. I hope it can help you.
You can create a new object based on some custom filter criteria by using a combination of Object.keys and the array .reduce method. Note this only works in es6:
var myObject = {"Key1":["a","b","c"], "Key2":["e","f","g"]}
function filterObjectByKey(obj, filterFunc) {
return Object.keys(obj).reduce((newObj, key) => {
if (filterFunc(key)) {
newObj[key] = obj[key];
}
return newObj;
}, {});
}
const filteredObj = filterObjectByKey(myObject, x => x === "Key1")
console.log(filteredObj)
Not sure what exactly are you trying to achieve, but if you want to have a set of keys that you would like to get the data for, you have quite a few options, one is:
var keys = ['alpha', 'bravo'];
var objectToFilterOn = {
alpha: 'a',
bravo: 'b',
charlie: 'c'
};
keys.forEach(function(key) {
console.log(objectToFilterOn[key]);
});

Round off decimals values in all objects of a Json object

This is my JSON string
[{"$id":"1","GeoName":"EAST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206},{"$id":"2","GeoName":"WEST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206}]"
This is my JSONobject before Stringyfying
**MyObj:**
0:Object
$id:"1"
Value1:18.44377295716579
GeoName:"EAST"
Value2:87.88221970554928
Value3:16.732108234801206
Value4:90.71955219607294
1:Object
$id:"2"
Value1:18.44377295716579
GeoName:"WEST"
Value2:87.88221970554928
Value3:16.732108234801206
Value4:90.71955219607294
Is there a way to round off all the values(or even individually value1,value2...) upto 2 decimal points in each every object of my JSON?
Like
0:Object
$id:"1"
Value1:18.44
GeoName:"EAST"
Value2:87.89
Value3:16.73
Value4:90.72
1:Object
$id:"2"
Value1:18.44
GeoName:"WEST"
Value2:87.89
Value3:16.73
Value4:90.71
I have tried using
Obj = JSON.parse(JSON.stringify(MyObj, function (GeoName, Value1) {
return Value1.toFixed ? Number(Value1.toFixed(2)) : Value1;
}));
Which did not work for me.
Is there a way i can achieve this by tweaking the above line of code or is there a better approach to solve this issue?
Edit1(After the approach suggested by wostex)
var numKeys = ['ShareValue','ReachValue','DepthValue','WidthValue'];
MyObj=Obj.map(e => Object.assign(e,Object.keys(e).filter(k => numKeys.includes(k)).map(v => Object.assign({[v]: parseFloat(e[v]).toFixed(2)}))))
This is How my object is looking like
0:Object
0:Object
ReachValue:87.88
1:Object
DepthValue:16.73
2:Object
ShareValue:18.44
3:Object
WidthValue:90.71
$id:"1"
ShareValue:18.44377295716579
GeoName:"EAST"
ReachValue:87.88221970554928
DepthValue:16.732108234801206
WidthValue:90.71955219607294
Edit2
Obj = JSON.parse(JSON.stringify(BubbleObj));
var numKeys = ['ShareValue','ReachValue','DepthValue','WidthValue'];
var MyObj=Obj.map(e => Object.assign(e,Object.keys(e).filter(k => numKeys.includes(k)).map(v => Object.assign({[v]: parseFloat(e[v]).toFixed(2)}))))
Here Obj has the JSON string from the first line of the question and BubbleObj has the Object which i mentioned as MyObj in the question.
The easy way is just to use map - and as long as your Value1-4 are always called that
var input = [{"$id":"1","GeoName":"EAST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206},{"$id":"2","GeoName":"WEST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206}];
var output = input.map(function(e) {
return {
$id: e.$id,
GeoName: e.GeoName,
Value1: Math.round(e.Value1*100) /100,
Value2: Math.round(e.Value2*100) /100,
Value3: Math.round(e.Value3*100) /100,
Value4: Math.round(e.Value4*100) /100
}
});
console.log(output);
If you dont want to hardcode it, you could look for any key starting Value - its a little more complex.
var input = [{"$id":"1","GeoName":"EAST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206},{"$id":"2","GeoName":"WEST","Value2":87.88221970554928,"Value4":90.71955219607294,"Value1":18.44377295716579,"Value3":16.732108234801206}];
var output = input.map(function(e) {
return Object.keys(e).reduce(function(p,n){
if(n.startsWith("Value"))
p[n] = Math.round(e[n]*100)/100;
else
p[n] = e[n];
return p;
},{})
});
console.log(output);
BTW you have duplicated keys 'Value3' in your first string, other than that you can do the following:
var j = [{"$id":"1","GeoName":"EAST","ShareValue":87.88221970554928,"ReachValue":90.71955219607294,"DepthValue":18.44377295716579,"WidthValue":16.732108234801206},{"$id":"2","GeoName":"WEST","ShareValue":87.88221970554928,"ReachValue":90.71955219607294,"DepthValue":18.44377295716579,"WidthValue":16.732108234801206}];
// your numeric keys
var numKeys = ['ShareValue','ReachValue','DepthValue','WidthValue'];
var res = j.map(e => Object.assign(e, // rewrite each object
...Object.keys(e).filter(k => numKeys.indexOf(k) > -1) // pick keys which include 'Value'
.map(v => Object.assign({[v]: parseFloat(e[v]).toFixed(2)})) // chop numbers
))
console.log(res)

generate js key-value object from string

I got a very common question but with a twist which is the reason for this post:
I want to create a key,value object from a string.
my string looks like this:
01§§foo§§bar§§someLink
(i can change the delimiter symbols to whatever i want, if there should be somehow a very tight solution with a specific symbol)
now, i want a key value object and most questions about this problem already got the datapair in the string,(like "id:01,title:foo") but thats not the case in my problem.
i want to generate something like this:
var modules = [
{"ID":"01", "title":"foo", "description":"bar","link":"someLink"},
//more entries from more strings
];
the reason for the key,value object is, that there are more of these strings which I convert from a database. I want it to be in a key,value object so its easier to work with the data later in my tool.
Thank you in advance
You could use Array#split for the string and an array for the keys.
var string = '01§§foo§§bar§§someLink',
moduleKeys = ["ID", "title", "description", "link"],
object = {};
string.split('§§').forEach(function (a, i) {
object[moduleKeys[i]] = a;
});
console.log(object);
A methode for multiple strings.
function getData(array) {
var moduleKeys = ["ID", "title", "description", "link"];
return array.map(function (string) {
var object = {};
string.split('§§').forEach(function (a, i) {
object[moduleKeys[i]] = a;
});
return object;
});
}
var strings = ['01§§foo§§bar§§someLink', '02§§foo§§bar§§someLink'];
console.log(getData(strings));

Underscore: How to return all values by array with keys

I have big object with a lot of key : value, and I have array with some keys from this object.
How to return values of this keys(array) by underscore?
I try some like this, but it's bull**
_.find(objectwithkeysandvalues , function(value){
return _.intersection(value,arraywithekeys)
});
You don't need Underscore for this task. Instead, you can use the map function to create a new array that contains the values specified by the keys in the old array:
var myValues = keys.map(function (key) {
return myObject[key]
});
You only need to map each value from your keys array to yourBigObject[value].
In Underscore this would look like this :
var keys = [ ... ]; // Keys from your big object
var obj = { ... }; // Your big object
var values = _.map(keys, function(value, index) {
return obj[value];
});
See this fiddle for experimenting.
Here's a solution using upcoming EcmaScript 7 Array Comprehensions available today via Babel.js.
Try it: Array Comprehensions Example.
ES7:
var obj = {
"key1": 1,
"key2": 2,
"key3": 3
}
var arr = ["key1"];
var values = [for(key of arr) obj[key]];
console.log(values);

Categories