I want to change a json array keys names from upper case letters to a lower case keys as the following
[
{
"_id": "581f2749fb9b6f22308f5063",
"WorkshopId": "1",
"WorkshopTitle": "workshop1",
"WorkshopPrice": "200",
"WorkshopDescription": "workshop1 is a test workshop",
"FloorNumber": "1",
"RoomNumber": "205",
"WorkshopLanguage": "english language",
"LastOnlineRegistrationDate": "15/10/2016",
"WorkshopDate": "1/11/2016",
"WorkshopStartTime": "8:00 AM",
"WorkshopEndTime": "11:00 AM",
"WorkshopRules": "Rules will be mentioned here",
"WorkshopCapacity": "200",
"Speaker": {
"SpeakerName": "John doe",
"AboutSpeaker": "About the speaker"
}
},
{
"_id": "581f27e796915434f44cd678",
"WorkshopId": "2",
"WorkshopTitle": "workshop2",
"WorkshopPrice": "200",
"WorkshopDescription": "workshop2 is a test workshop",
"FloorNumber": "1",
"RoomNumber": "205",
"WorkshopLanguage": "english language",
"LastOnlineRegistrationDate": "15/10/2016",
"WorkshopDate": "1/11/2016",
"WorkshopStartTime": "11:00 AM",
"WorkshopEndTime": "02:00 PM",
"WorkshopRules": "Rules will be mentioned here",
"WorkshopCapacity": "200",
"Speaker": {
"SpeakerName": "Jane doe",
"AboutSpeaker": "Jane doe - About the speaker"
}
}
]
for example WorkshopId must be changed to workshopid, I have a function in node js that query a collection in mongodb and return the json :
getWorkshops: function (db, response) {
db.collection('Workshops').find().toArray(function (err, results) {
var convertedArr = [];
//convert the json.
response.send(JSON.stringify(convertedArr));
});
any help?
This will map an object's keys to lowercase:
var upperCased = [
{ ID: 1, NAME: 'Fred' },
{ ID: 2, NAME: 'Sarah' },
{ ID: 3, NAME: 'Joe' },
];
var lowerCased = upperCased.map(function(item) {
var mapped = {};
for (var key in item) {
mapped[key.toLowerCase()] = item[key];
}
return mapped;
});
https://jsfiddle.net/5ouebw4b/2/
You could to it with a custom toJSON() function:
getWorkshops: function (db, response) {
db.collection('Workshops').find().toArray(function (err, results) {
results.toJSON = function () {
var newArr = [];
for (var obj in this) {
if (!this.hasOwnProperty(obj) || 'toJSON' === obj) continue;
var newObj = {};
for (var prop in this[obj]) {
if (!this[obj].hasOwnProperty(prop)) continue;
newObj[prop.toLowerCase()] = this[obj][prop];
}
newArr.push(newObj);
}
return newArr;
};
response.send(JSON.stringify(results));
});
}
Related
Any guidance or reference is appreciated.
Using javascript's (map reduce and filter), I am trying to get a collection of all available rooms across multiple vendors in the given JSON array. The logic for this :
**User Input **: checkIn Date, checkOut Date and Property Name
**Filter Logic **
Check is the item availableFrom and availableTo dates fall in the range of checkIn and checkOut.
Check if the item propertyName matches the user input
Iterate through the items to get the common rooms
I have a JSON structure is :
var callOutResult =
[
{
"vendorId": "1",
"vendorName": "ABC",
"vendorPropertyId": "100",
"propertyName": "Some Name",
"availableFrom": "2012-04-01T15:00:00.001Z",
"availableTo": "2012-04-25T12:00:00.001Z",
"available": {
"floor1": ["101","105","106"],
"floor2": ["202","204","208"],
"floor3": ["301","304","307"],
"floor4": ["405","409","410"],
"floor5": ["502","504","506"],
"floor6": ["602","607","609"]
}
},
{
"vendorId": "2",
"vendorName": "XYZ",
"vendorPropertyId": "300",
"propertyName": "Some Name",
"availableFrom": "2012-04-10T15:00:00.001Z",
"availableTo": "2012-05-20T12:00:00.001Z",
"available": {
"floor1": ["104","106","107"],
"floor2": ["208","214"]
}
},
{
"vendorId": "3",
"vendorName": "PQR",
"vendorPropertyId": "450",
"propertyName": "Some Name",
"availableFrom": "2012-01-23T15:00:00.001Z",
"availableTo": "2012-06-25T12:00:00.001Z",
"available": {
"floor1": ["101","102","103"],
"floor2": ["208","212"],
"floor3": ["302","306","315"],
"floor4": ["415","409","420"]
}
}
]
Code I have thus far
var checkInDate = new Date("2012-04-10");
var checkOutDate = new Date("2012-04-22");
var propertyName = 'Some Name'
// Check in & Check Out Date Filter
var filter1 = callOutResult.filter(function (arrayItem) {return arrayItem.availableFrom <= checkOutDate && arrayItem.availableTo >= checkInDate});
// Property Name Filter
var filter2 = filter1.filter(function (arrayItem) {return arrayItem.propertyName === propertyName});
result = Object
.values(filter2)
.reduce(function(a, b){
// CANNOT FIGURE OUT THE LOGIC TO ITERATE THROUGH THE rooms.
});
My goal is to filter the array to find available rooms. Reference to article, other sample code, anything that will guide me.
If you were trying to find the room(s) that fall within the specified checkin and checkout dates, have the required propertyName and are found in all the matched items, then the following might be helpful:
var callOutResult =
[
{
"vendorId": "1",
"vendorName": "ABC",
"vendorPropertyId": "100",
"propertyName": "Some Name",
"availableFrom": "2012-04-01T15:00:00.001Z",
"availableTo": "2012-04-25T12:00:00.001Z",
"available": {
"floor1": ["101","105","106"],
"floor2": ["202","204","208"],
"floor3": ["301","304","307"],
"floor4": ["405","409","410"],
"floor5": ["502","504","506"],
"floor6": ["602","607","609"]
}
},
{
"vendorId": "2",
"vendorName": "XYZ",
"vendorPropertyId": "300",
"propertyName": "Some Name",
"availableFrom": "2012-04-10T15:00:00.001Z",
"availableTo": "2012-05-20T12:00:00.001Z",
"available": {
"floor1": ["104","106","107"],
"floor2": ["208","214"]
}
},
{
"vendorId": "3",
"vendorName": "PQR",
"vendorPropertyId": "450",
"propertyName": "Some Name",
"availableFrom": "2012-01-23T15:00:00.001Z",
"availableTo": "2012-06-25T12:00:00.001Z",
"available": {
"floor1": ["101","102","103"],
"floor2": ["208","212"],
"floor3": ["302","306","315"],
"floor4": ["415","409","420"]
}
}
];
// convert date strings into Date objects:
callOutResult.forEach(e=>["From","To"].forEach(ft=>e["available"+ft]=new Date(e["available"+ft])));
var checkInDate = new Date("2012-04-10T15:10:00.001Z");
var checkOutDate = new Date("2012-04-22T09:00:00.001Z");
var propertyName = 'Some Name';
// check in & check out date and propertyName filter:
var filter = callOutResult.filter(function(itm) {
return itm.availableFrom <= checkInDate && itm.availableTo >= checkOutDate && itm.propertyName === propertyName});
// check the existence of the room(s) for all matched vendors:
console.log(filter.map(e=>Object.values(e.available).flat(2)) // flatten rooms for each vendor
.reduce((a,c)=>{return a.filter(e=>c.some(f=>e==f))})) // a room must occur in each vendor object!
If the result should contain only those rooms (on their individual floors) that
fulfil both timing and
propertyName conditions
and are only listed once,
then the following might be helpful:
var callOutResult = [{"vendorId": "1","vendorName": "ABC","vendorPropertyId": "100","propertyName": "Some Name","availableFrom": "2012-04-01T15:00:00.001Z","availableTo": "2012-04-25T12:00:00.001Z","available": {"floor1": ["101", "105", "106"],"floor2": ["202", "204", "208"],"floor3": ["301", "304", "307"],"floor4": ["405", "409", "410"],"floor5": ["502", "504", "506"],"floor6": ["602", "607", "609"]}},{"vendorId": "2","vendorName": "XYZ","vendorPropertyId": "300","propertyName": "Some Name","availableFrom": "2012-04-10T15:00:00.001Z","availableTo": "2012-05-20T12:00:00.001Z","available": {"floor1": ["104", "106", "107"],"floor2": ["208", "214"]}},{"vendorId": "3","vendorName": "PQR","vendorPropertyId": "450","propertyName": "Some Name","availableFrom": "2012-01-23T15:00:00.001Z","availableTo": "2012-06-25T12:00:00.001Z","available": {"floor1": ["101", "102", "103"],"floor2": ["208", "212"],"floor3": ["302", "306", "315"],"floor4": ["415", "409", "420"]}}];
// convert date strings into Date objects:
callOutResult.forEach(e => ["From", "To"].forEach(ft => e["available" + ft] = new Date(e["available" + ft])));
var checkInDate = new Date("2012-04-10T15:10:00.001Z");
var checkOutDate = new Date("2012-04-22T09:00:00.001Z");
var propertyName = 'Some Name';
// check in & check out date and propertyName filter:
var dateProp = callOutResult.filter(function(itm) {
return itm.availableFrom <= checkInDate && itm.availableTo >= checkOutDate && itm.propertyName === propertyName
});
const res = Object.entries(dateProp.reduce((a, e) => {
Object.entries(e.available).forEach(([fl, rms]) => {
let afl = a[fl] ??= {};
rms.forEach(r => afl[r] = afl[r] ? afl[r] + 1 : 1);
});
return a;
}, {})).map(([fl, rms]) => Object.fromEntries([
[fl, Object.entries(rms).filter(([r, cnt]) => cnt == 1).map(([r]) => r)]
]));
console.log(JSON.stringify(res));
Hi i'm trying to make an Object from and array of objects and other objects for a customs final object (example in code) . Iv'e tried to do forEach on the array and create a new object and push it to the final array but had no luck. the numbers in snapObj could have the digit that's not the first in the object (digit0 could be digit1...) in dataArr this makes it hard for me to find the correct one and represent as needed. any recommendations?
var dataArr = {};
//First array of objects
var arrayContactsWithNames = [{
"digits0": "5555648583",
"digits1": "4155553695",
"name": "Kate Bell",
}, {
"digits0": "5554787672",
"digits1": "4085555270",
"digits2": "4085553514",
"name": "Daniel Higgins Jr.",
}, {
"digits0": "8885555512",
"digits1": "8885551212",
"name": "John Appleseed",
}, {
"digits0": "5555228243",
"name": "Anna Haro",
}, {
"digits0": "5557664823",
"digits1": "7075551854",
"name": "Hank M. Zakroff",
}, {
"digits0": "5556106679",
"name": "David Taylor",
}];
// Second object
var snapObj = {
"5556106679": "test 1",
"7075551854": "test 2",
"8885551212": "test 1"
};
/* This is what I want to get:
var dataArr = [{
"test 1": {
"5556106679": "David Taylor",
"8885551212": "John Appleseed"
}
}, {
"test 2": Object {
"7075551854": "Hank M. Zakroff",
}
}]
*/
// This is what I tried
arrayContactsWithNames.forEach((i) => {
if (i in snapObject) {
const newObj = Object.assign({snapObject[i],{ name },{digits${i}}});
dataArr.push(newObj);
}
});
The logic is to first create a Object dictionary of the form number:name and use it for lookup from the second object. This is most optimal since it only takes O(1) to lookup a key in an object.
var arrayContactsWithNames = [{
"digits0": "5555648583",
"digits1": "4155553695",
"name": "Kate Bell",
}, {
"digits0": "5554787672",
"digits1": "4085555270",
"digits2": "4085553514",
"name": "Daniel Higgins Jr.",
}, {
"digits0": "8885555512",
"digits1": "8885551212",
"name": "John Appleseed",
}, {
"digits0": "5555228243",
"name": "Anna Haro",
}, {
"digits0": "5557664823",
"digits1": "7075551854",
"name": "Hank M. Zakroff",
}, {
"digits0": "5556106679",
"name": "David Taylor",
}];
var snapObj = {
"5556106679": "test 1",
"7075551854": "test 2",
"8885551212": "test 1"
};
let parsedArr = arrayContactsWithNames.reduce((acc,{name,...digits}) => {
Object.values(digits).forEach(digit => { acc[digit] = name });
return acc;
}, {}); // create a { number : name } mapping with some es6 magic. Refer Object destructuring and spread operator to know how the digit0,digit1 etc are extracted.
// console.log(parsedArr)
let parsedObj = Object.keys(snapObj).reduce((acc,num) => {
let val = snapObj[num]
if(!acc[val])
acc[val] = {}
acc[val][num] = parsedArr[num]; // use the lookup object with the number
return acc;
},{}); // A simple reducer to create a new object in the desired shape.
console.log(parsedObj);
If I understand correctly what you want, consider this sample:
const data = {}
const snap = {
'5556106679': 'test 1',
'7075551854': 'test 2',
'8885551212': 'test 1'
}
const objects = [
{
'digits0': '5555648583',
'digits1': '4155553695',
'name': 'Kate Bell',
},
{
'digits0': '5554787672',
'digits1': '4085555270',
'digits2': '4085553514',
'name': 'Daniel Higgins Jr.',
},
{
'digits0': '8885555512',
'digits1': '8885551212',
'name': 'John Appleseed',
},
{
'digits0': '5555228243',
'name': 'Anna Haro',
},
{
'digits0': '5557664823',
'digits1': '7075551854',
'name': 'Hank M. Zakroff',
},
{
'digits0': '5556106679',
'name': 'David Taylor',
}]
for (const key in snap)
{
if (!data[snap[key]])
{
data[snap[key]] = {}
}
for (const object of objects)
{
for (const i in object)
{
if (object[i] === key)
{
data[snap[key]][key] = object.name
break
}
}
}
}
document.querySelector('textarea').value = JSON.stringify(data, null, ' ')
<textarea cols="50" rows="10"></textarea>
I have the following object:
var obj = { 2017-05-28: 76.16108625212159, 2017-02-12: 70.32183347555772, 2017-05-21: 74.21070693205216, 2017-04-23: 78.49819059107358, 2017-03-05: 73.36286201022146, 2017-04-02: 79.07588060050237, 2017-01-29: 79.07021235890568, 2017-03-26: 74.79360018220122, 2017-01-22: 71.80166785183269, 2017-04-09: 72.68569443640364 };
I would like to sort it by date, beginning from January, but I have no idea how to do this.
What do you think, is it possible in JS ?
Thanks in advance,
The order of keys is not guaranteed in an object. you can convert your data structure into a sorted array as shown below and iterate over the array in order for your needs:
var obj = {
"2017-05-28": 76.16108625212159,
"2017-02-12": 70.32183347555772,
"2017-05-21": 74.21070693205216,
"2017-04-23": 78.49819059107358,
"2017-03-05": 73.36286201022146,
"2017-04-02": 79.07588060050237,
"2017-01-29": 79.07021235890568,
"2017-03-26": 74.79360018220122,
"2017-01-22": 71.80166785183269,
"2017-04-09": 72.68569443640364
};
var sortedArray = Object.keys(obj).sort().map(function(key) {
return {
date: key,
value: obj[key]
}
});
console.log(sortedArray);
/**Outputs:
[
{
"date": "2017-01-22",
"value": 71.80166785183269
},
{
"date": "2017-01-29",
"value": 79.07021235890568
},
{
"date": "2017-02-12",
"value": 70.32183347555772
},
{
"date": "2017-03-05",
"value": 73.36286201022146
},
{
"date": "2017-03-26",
"value": 74.79360018220122
},
{
"date": "2017-04-02",
"value": 79.07588060050237
},
{
"date": "2017-04-09",
"value": 72.68569443640364
},
{
"date": "2017-04-23",
"value": 78.49819059107358
},
{
"date": "2017-05-21",
"value": 74.21070693205216
},
{
"date": "2017-05-28",
"value": 76.16108625212159
}
]
**/
var obj = '{ "2017-05-28": "76.16108625212159", "2017-02-12": "70.32183347555772", "2017-05-21": "74.21070693205216", "2017-04-23": "78.49819059107358", "2017-03-05": "73.36286201022146", "2017-04-02": "79.07588060050237", "2017-01-29": "79.07021235890568", "2017-03-26": "74.79360018220122", "2017-01-22": "71.80166785183269", "2017-04-09": "72.68569443640364" }';
pobject = JSON.parse(obj);
arr = Object.keys(pobject);
sorted = arr.sort();
len = sorted.length;
for(i=0;i<len;i++)
{
val= pobject[sorted[i]];
console.log(val);
}
This will work
Hope this helps..!
Using Array.prototype.sort() and Array.prototype.reduce()
You can not order object proprieties. so you may need to convert your object to an array
Example
var obj = {
"2017-05-28": 76.16108625212159,
"2017-02-12": 70.32183347555772,
"2017-05-21": 74.21070693205216,
"2017-04-23": 78.49819059107358,
"2017-03-05": 73.36286201022146,
"2017-04-02": 79.07588060050237,
"2017-01-29": 79.07021235890568,
"2017-03-26": 74.79360018220122,
"2017-01-22": 71.80166785183269,
"2017-04-09": 72.68569443640364
},
sortedArr = Object.keys(obj)
.sort(function (a, b) {
return new Date(a) - new Date(b)
})
.reduce(function (acc, item, index) {
acc.push({
date: item,
value: obj[item]
});
return acc;
}, []);
console.log(sortedArr);
Thanks #Shivam for your note
EDIT:
I believe this is a different problem than a simple _.groupBy because I am trying to group by all keys and returning an hashmap not an array.
I have an array of the following objects:
items = [
{ created_at: "01/01/2016", name: "bob", age: 21, height: 60 },
{ created_at: "01/02/2016", age: 22, height: 70 },
{ created_at: "01/03/2016", name: "alice", age: 23 }
]
And I am trying to transform it into this format:
{
"name": [
{
"value": "bob",
"created_at": "01/01/2016"
},
{
"value": "alice",
"created_at": "01/03/2016"
}
],
"age": [
{
"value": 21,
"created_at": "01/01/2016"
},
{
"value": 22,
"created_at": "01/02/2016"
},
{
"value": 23,
"created_at": "01/03/2016"
}
],
"height": [
{
"value": 60,
"created_at": "01/01/2016"
},
{
"value": 70,
"created_at": "01/02/2016"
}
]
}
My requirement is I am ignoring the created_at field, but grouping everything else.
One solution is:
var items = [
{ created_at: "01/01/2016", name: "bob", age: 21, height: 60 },
{ created_at: "01/02/2016", age: 22, height: 70 },
{ created_at: "01/03/2016", name: "alice", age: 23 }
]
var store = {}
for(var i=0; i < items.length; i++) {
var item = items[i]
for(key in item) {
if(key === "created_at") {
continue
}
value = item[key]
if(!store[key]) {
store[key] = []
}
store[key].push({
value: value,
created_at: item.created_at
})
}
}
$('pre').text(JSON.stringify(store, null, 2))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body><pre></pre></body>
I was wondering if there was some cool way to do it in lodash ... maybe using .map() or .groupBy() or something? I don't quite get how to use them properly and am trying to learn new, more elegant ways to write the code.
You asked specifically about lodash, and so this answer is constructed using lodash.
Note I'm using the _.chain method - this makes it convenient to chain multiple operations rather than running them each separately.
One way (I'm sure there are many others) that gets it pretty close (not perfect) is this:
items = _.chain(items)
.map(function(n) {
var created = _.get(n, 'created_at');
var arr = [];
_.each(n, function(n, k) {
if (k != 'created_at') {
arr.push({
'field': k,
'value': n,
'created_at': created
});
}
});
return arr;
})
.flatten()
.groupBy('field')
.value();
Which results in a collection that looks like this:
{ "name":
[
{ "field": "name", "value": "bob", "created_at": "01/01/2016" },
{ "field": "name", "value": "alice", "created_at": "01/03/2016" }
],
"age": [
....
Here's a Fiddle for playing around with this code.
Using reduce might be the shortest way.
var baseKey = 'created_at';
var result = items.reduce(function(col, item) {
Object.keys(item).forEach(function(key) {
if (key === baseKey || !item[key]) return;
var o = { value: item[key] };
o[baseKey] = item[baseKey];
(col[key] = col[key] || []).push(o);
});
return col;
}, {});
JSFiddle Demo: https://jsfiddle.net/pLcv1am2/6/
I want to merge item and purchases array of json into one by matching their property value.
Here's the source :
{
"item": [
{
"invoiceId": 1
},
{
"invoiceId": 2
},
{
"invoiceId": 3
}
],
"purchase": [
{
"id": "1",
"date": "12/1/2014"
},
{
"id": "2",
"date": "12/1/2014"
},
{
"id": "3",
"date": "12/1/2014"
}
]
}
I want to produce something like this :
{
"combined": [
{
"invoiceId": 1,
"id": "1",
"date": "12/1/2014"
},
{
"invoiceId": 2,
"id": "2",
"date": "12/1/2014"
},
{
"invoiceId": 3,
"id": "3",
"date": "12/1/2014"
}
]
}
How can I match the item.invoiceId with purchase.id?
Solution
assuming obj is your object
var new_obj = {combined:[]};
obj["purchase"].forEach(function(a) {
obj["item"].forEach(function(b){
if (+b["invoiceId"]===(+a["id"])) {
a["invoiceId"] = b["invoiceId"] || 0;//WILL MAKE INVOICEID 0 IF IT IS NOT DEFINE. CHANGE 0 TO YOUR NEEDS
new_obj.combined.push(a);
}
});
});
How it works
The first .forEach() loops through obj.purchase. Then we loop through obj.item To check if their is a matching invoiceId (if you don't need to make sure their is a matching invoiceId, use the alternate code). Then, we simply add a new value to the new_obj
The result (copied from console) is:
{
"combined":[
{
"id":"1",
"date":"12/1/2014",
"invoiceId":1
},
{
"id":"2",
"date":"12/1/2014",
"invoiceId":2
},
{
"id":"3",
"date":"12/1/2014",
"invoiceId":3
}
]
}
Alternative Code
Use this if you don't need to make sure, invoiceId is there
var new_obj = {combined:[]};
obj["purchase"].forEach(function(a){a["invoiceId"]=a["id"];new_obj.combined.push(a);});
One way of achieving what you want will be
var result = {};
var getMatchingPurchase = function(invoiceId) {
return data.purchase.filter(function(purchase) {
return invoiceId == purchase.id;
})[0];
};
result.combined = data.item.map(function(invoice) {
var purchase = getMatchingPurchase(invoice.invoiceId);
return {
invoiceId: invoice.invoiceId,
id: purchase.id,
date: purchase.date
};
});
console.log(result);
It will print like bellow
{ combined:
[ { invoiceId: 1, id: '1', date: '12/1/2014' },
{ invoiceId: 2, id: '2', date: '12/1/2014' },
{ invoiceId: 3, id: '3', date: '12/1/2014' } ] }
Note:- I'm using map and filter functions which are not supported in IE8. If you want to use in IE8 you have to use for loop.
If you have to support old browsers like IE8 (poor guy...), note that the native forEach might not be supported, in this case you can use lodash for cross-browser compatibility:
function getCombinedResult(source){
var combinedList = [];
_.each(source.item, function(item){
_.each(source.purchase, function(purchase){
if (item['invoiceId'].toString() != purchase['id'].toString()) return;
var combinedItem = _.extend(item, purchase)
combinedList.push(combinedItem);
});
})
return {"combined": combinedList};
}