Filter objects in Javascript - javascript

Is there quick way to filter an array of objects to return only a few properties in each object?
For example we have the data below:
var objArr = [{
"Title": "July 13 - July 19 2014",
"displayAd_imp": "3,500",
"videoAd_imp": "1.5",
"tv_imp": "0.52",
"Date": "2014-07-17T00:00:00.000Z",
"WeekNo": 29
}, {
"Title": "July 20 - July 26 2014",
"displayAd_imp": "1,600",
"videoAd_imp": "2.55",
"tv_imp": "0.052",
"Date": "2014-07-24T00:00:00.000Z",
"WeekNo": 30
}, {
"Title": "July 27 - Aug 2 2014",
"displayAd_imp": "1,500",
"videoAd_imp": "2.1",
"tv_imp": "0.122",
"Date": "2014-07-31T00:00:00.000Z",
"WeekNo": 31
}]
I'm trying to filter the array above to get another array with only videoAd_imp, videoAd_imp, tv_imp. so it would look like this:
[{
"displayAd_imp": "3,500",
"videoAd_imp": "1.5",
"tv_imp": "0.52",
}, {
"displayAd_imp": "1,600",
"videoAd_imp": "2.55",
"tv_imp": "0.052",
}, {
"displayAd_imp": "1,500",
"videoAd_imp": "2.1",
"tv_imp": "0.122",
}]
Thanks in advance!

Use Array.map like bellow
If you want new references to all objects.
var newArr = objArr.map(function (obj) {
return {displayAd_imp:obj.displayAd_imp,videoAd_imp:obj.videoAd_imp,tv_imp:obj.tv_imp};
})
console.log(newArr);
If you want to get original references use like bellow
var newArr = objArr.map(function (obj) {
delete obj.Date;
delete obj.WeekNo;
delete obj.Title
return obj;
})

var objArr = [{/* ... */}];
// cache the array length to avoid resolving it on every iteration
var arrLength = objArr.length;
// your new array
var newArr = [];
for(var i=0; i<arrLength; i++){
// push only the properties you want to the new array
newArr.push({
displayAd_imp: objArr[i].displayAd_imp,
videoAd_imp: objArr[i].videoAd_imp,
tv_imp: objArr[i].tv_imp
});
}
// show it in the console
console.log(newArr);
JS Fiddle Demo

Here is a simple solution
var newArr = []
for(var i=0;i<objArr.length) {
newArr.push({
displayAd_imp: objArr[i].displayAd_imp,
videoAd_imp: objArr[i].videoAd_imp,
tv_imp: objArr[i].tv_imp
}
);
}

Related

Add another key...value pair to objects

I want to add more key... value pairs to each of the objects. Is it possible to do that?
Right now I have objects that look like:
{"year":2014,"num":115.5}
{"year":2016,"num":0.0}
{"year":2017,"num":8.28}
{"year":2018,"num":0.0}
I have an array of colors:
let colors = ['#42d4f4','#e6194B','#3cb44b','#911eb4'];
I want to now add these colors to my objects.
I want to make it look like so:
{"year":2014,"num":115.5, "colors": '#42d4f4'}
{"year":2016,"num":0.0, "colors": '#e6194B'}
{"year":2017,"num":8.28, "colors": '#3cb44b'}
{"year":2018,"num":0.0, "colors": '#911eb4'}
Is there a way for me to do that without writing many many if's?
You can use map to loop thru the array. Use spread syntax to shallow copy the object and add the colors property using the index.
let arr = [{
"year": 2014,
"num": 115.5
}, {
"year": 2016,
"num": 0.0
}, {
"year": 2017,
"num": 8.28
}, {
"year": 2018,
"num": 0.0
}];
let colors = ['#42d4f4', '#e6194B', '#3cb44b', '#911eb4'];
let result = arr.map((o, i) => ({ ...o, colors: colors[i] || null }));
console.log(result);
If you want to update the existing variable, you can use forEach
let arr = [{
"year": 2014,
"num": 115.5
}, {
"year": 2016,
"num": 0.0
}, {
"year": 2017,
"num": 8.28
}, {
"year": 2018,
"num": 0.0
}];
let colors = ['#42d4f4', '#e6194B', '#3cb44b', '#911eb4'];
arr.forEach((o, i) => o.colors = colors[i] || null);
console.log(arr);
You can map over the array and return all of the objects with a new key color.
let data =[
{"year":2014,"num":115.5},
{"year":2016,"num":0.0},
{"year":2017,"num":8.28},
{"year":2018,"num":0.0}
];
let colors = ['#42d4f4','#e6194B','#3cb44b','#911eb4'];
let newData = colors.map((color, index) => ({...data[index], color}));
console.log(newData);
If you're not familiar with ES6 syntax, this is the same as:
let data =[
{"year":2014,"num":115.5},
{"year":2016,"num":0.0},
{"year":2017,"num":8.28},
{"year":2018,"num":0.0}
];
let colors = ['#42d4f4', '#e6194B', '#3cb44b', '#911eb4'];
let newData = colors.map(function(colorHex, index) {
return {
year: data[index].year,
num: data[index].num,
color: colorHex
}
})
console.log(newData) // [{"year":2014,"num":115.5, "colors": '#42d4f4'}, ...]

How to generate an array of unique objects from api?

I'm trying to disable booked times from calendar, depending on the date. My goal is to create an array, which holds objects with single date and array of booked times.
I have created an api, which outputs something like this:
"bookings": [
{
"_id": "5ce1b8792598adasf452",
"workType": "Nail polishing",
"client": "Mary Johnson",
"date": "2019-05-31T00:00:00.000Z",
"bookingTime": "09:00"
},
{
"_id": "5ce1b8753hs53gasf452",
"workType": "Makeup",
"client": "Kate Bush",
"date": "2019-05-31T00:00:00.000Z",
"bookingTime": "10:00"
}
]
I've tried using Sets, filters, but I just can't seem to wrap my head around how to implement it to my own code.
Snippet of my code:
bookedTimes: []
fetchBookedTimes() {
axios.get("http://localhost:8080/api/bookings").then(res => {
for (var i = 0; i < res.data.bookings.length; i++) {
this.bookedTimes.push({
date: moment(res.data.bookings[i].date).format("YYYY-MM-DD"),
times: [res.data.bookings[i].bookingTime.substring(0,2)]
});
}
});
}
I expect the output to be
bookedTimes: [
{
date: "2019-05-31",
times: ["09", "10"]
},
{
date: "2019-06-01",
times: ["10", "11"]
}
]
But the actual output is
bookedTimes: [
{
date: "2019-05-31",
times: ["09"]
},
{
date: "2019-05-31",
times: ["10"]
},
{
date: "2019-06-01",
times: ["10"]
},
{
date: "2019-06-01",
times: ["11"]
}
]
As per the code, the actual output is correct. You are looping the response and pushing the data to an array. If you want to group them by date, then you have to create an object and then convert it to the expected output.
var result = res.data.bookings.reduce(function (defaultValue, booking) {
var date = moment(booking.date).format("YYYY-MM-DD");
defaultValue[date] = defaultValue[date] || {date: date, times: []};
defaultValue[date].times.push(booking.bookingTime.substring(0,2));
return defaultValue;
}, {});
console.log(Object.values(result));
You can simply use reduce()
const arr = [
{
"_id": "5ce1b8792598adasf452",
"workType": "Nail polishing",
"client": "Mary Johnson",
"date": "2019-05-31T00:00:00.000Z",
"bookingTime": "09:00"
},
{
"_id": "5ce1b8753hs53gasf452",
"workType": "Makeup",
"client": "Kate Bush",
"date": "2019-05-31T00:00:00.000Z",
"bookingTime": "10:00"
},
{
"_id": "5ce1b8753hs53gasf452",
"workType": "Makeup",
"client": "Kate Bush",
"date": "2019-06-31T00:00:00.000Z",
"bookingTime": "11:00"
},
{
"_id": "5ce1b8753hs53gasf452",
"workType": "Makeup",
"client": "Kate Bush",
"date": "2019-06-31T00:00:00.000Z",
"bookingTime": "12:00"
}
]
const res = arr.reduce((ac,{date,bookingTime}) => {
ac[date] = ac[date] || {date,bookingTime:[]}
ac[date].bookingTime.push(bookingTime.slice(0,2));
return ac;
},{})
console.log(Object.values(res))
You're pushing values directly into array but you need to group them by date so you can use an object and then push values to array in the end
Here temp is used to group values by date
We check for date it exists we push the time value to times array if not we create a new property on temp
In the end we push values to this.bookedTimes array
fetchBookedTimes() {
axios.get("http://localhost:8080/api/bookings").then(res => {
let temp = {}
for (var i = 0; i < res.data.bookings.length; i++) {
let date = moment(res.data.bookings[i].date).format("YYYY-MM-DD"),
let time = [res.data.bookings[i].bookingTime.substring(0,2)]
temp[date] = temp[date] || {date: date, times:[]}
temp[date].times.push(time)
});
}
this.bookedTimes.push(Object.values(temp))
});
}
First, check if the date of already in the array. Check if 'times' already exist in 'object.times', if not, push it to the 'object.times' array.
Please see the code below.
const date = moment(res.data.bookings[i].date).format("YYYY-MM-DD");
const times = res.data.bookings[i].bookingTime.substring(0, 2);
const arrayIndex = bookedTimes.findIndex(item => item.date === date);
//Check if date already exist in array
if (arrayIndex !== -1) {
//Check if 'times' already exist in 'object.times'
if (!bookedTimes[arrayIndex].times.includes(times)) {
//Push 'times' in 'object.times'
bookedTimes[arrayIndex].times.push(times);
}
} else {
//Push a new object into the array
bookedTimes.push({
date: date,
times: [times]
});
}

Replace JSON Object Programmatically

I'm looking for the most effective way to replace a JSON Object in a file.
20150628 - Update at the bottom of this post
Here's the scenario:
I have a bunch of JSON files (many) and in these files are large chunks of JSON (sometimes 20-30K lines of it). These are configurations for various testing routines we have. Recently, a change was required to change an object from this:
"createdAt": {
"year": 2014,
"month": 11,
"dayOfMonth": 24,
"hourOfDay": 2,
"minute": 22,
"second": 54
}
to a format like this:
"createdAt":"2015-05-12T21:14:51Z"
Let's even make this easier. I want to replace all of the createdAt and updatedAt fields in my JSON object (which there can be many) with:
"createdAt":"2015-05-12T21:14:51Z"
or
"updatedAt":"2015-05-12T21:14:51Z"
There are NUMEROUS (100's of these) objects in each file, with different values for the fields. I need to go through and replace every createdAt and updatedAt object with the new format. The date's do not matter. I can have them be anything.
I can do this by hand, but it will literally take me a day or two to do of full time work (I know, I tried to do one file and after 1/2 hour I gave up, it was taking way too long).
How can I do this programmatically?
Regex? Sed? Something else?
Final note: I only need to do this once. After that, I won't need to do it again.
Thanks for any tips!
Example JSON: (Just imagine the real one is 30,000 lines!) :)
{ "products": [
{
"displayOrder": 3,
"product": {
"foo": "bar",
"createdAt": {
"year": 2014,
"month": 11,
"dayOfMonth": 24,
"hourOfDay": 2,
"minute": 22,
"second": 54
},
"description": "Fizz Bin",
"id": "8765309",
"modelNumber": "call-it",
"name": "Boom",
"price": {
"amount": 100,
"currency": "USD"
},
"type": "Active",
"updatedAt": {
"year": 2015,
"month": 1,
"dayOfMonth": 27,
"hourOfDay": 19,
"minute": 33,
"second": 25
}
}
},
{
"displayOrder": 4,
"product": {
"foo": "barx",
"createdAt": {
"year": 2013,
"month": 1,
"dayOfMonth": 4,
"hourOfDay": 3,
"minute": 2,
"second": 5
},
"description": "Fizzy Stuff",
"id": "876511111",
"modelNumber": "zoom-zoom-1000",
"name": "Zoom Zoom 1000",
"price": {
"amount": 1000,
"currency": "USD"
},
"type": "Active",
"updatedAt": {
"year": 2011,
"month": 5,
"dayOfMonth": 25,
"hourOfDay": 15,
"minute": 35,
"second": 55
}
}
}
]
}
UPDATE 20150628
For those wondering, here's the gulpfile I wrote to accomplish exactly what I wanted. It is based off of the accepted answer. It will recursively search the tree for what I'm looking for an replace it when found. Its not the prettiest thing in the world, but it did exactly what I needed and saved me a couple weeks of manual time. Total time to process all my files? Under 100ms. Amazing.
var gulp = require('gulp');
var change = require('gulp-change');
function searchTreeForDates(obj) {
if(typeof(obj) === 'object') {
for (var key in obj) {
if (typeof(obj[key]) === 'object' && (key === 'createdAt' || key === 'updatedAt')) {
obj[key] = "2015-06-29T00:53:00Z";
} else {
obj[key] = searchTreeForDates(obj[key])
}
}
}
return obj;
}
function updateDate(content) {
var obj = JSON.parse(content);
obj = searchTreeForDates(obj);
return JSON.stringify(obj);
}
gulp.task('change', function() {
return gulp.src('*.json')
.pipe(change(updateDate))
.pipe(gulp.dest('changed/'))
});
Here is an initial stab. You implement your own "date parsing logic." It requires you to install gulp. And save this in a gulpfile.js . You would need to possibly loop over all the properties that are "date" objects. But that logic isn't that hard.
var gulp = require('gulp');
var change = require('change');
function translateDate(dateField){
return dateField.A + dateField.b + ...;
}
function updateDate(content) {
var obj = JSON.parse(content);
//loop over the obj properties and call the below
// for the ones you want to change.
obj.dateField = translateDate(obj.dateField);
return JSON.stringify(obj);
}
gulp.task('change', function() {
return gulp.src('**/*.json')
.pipe(change(updateDate))
.pipe(gulp.dest('changed/'))
});
Why not manually?
function formatDate(dateObject){
var formattedDate =
dateObject['year']+'-'+
dateObject['month']+'-'+
dateObject['dayOfMonth']+'T'+
dateObject['hourOfDay']+':'+
dateObject['minute']+':'+
dateObject['second']+'Z';
}
var jsonArray = {...};
for(var key in jsonArray){
for(var i = 0; i < jsonArray[key].length; i++){
jsonArray[key][i]['createdAt'] = formatDate(jsonArray[key]['createdAt']);
jsonArray[key][i]['updatedAt'] = formatDate(jsonArray[key]['updatedAt']);
}
}
Open each file, change the property with a convert function and then save the new JSON:
function changeDate(obj) {
var newObject = obj.year + '-' + obj.month + '-' + obj.dayOfMonth + 'T' + obj.hourOfDay + ':' + obj.minute + ':' + obj.second;
return newObject;
}
// here you open the file and stores it's content in the products variable.
for (var i = 0; i < products.length; i++) {
var product = products[i];
product.product.createdAt = changeDate(product.product.createdAt);
product.product.updatedAt = changeDate(product.product.updatedAt);
}
// .. now you need to save the modified json

Array JSON in javascript

My json is:
[
{
"_id":{
"time":1381823399000,
"new":false,
"timeSecond":1381823399,
"machine":263168773,
"inc":-649466399
},
"asset":"RO2550AS1",
"Salt Rejection":"90%",
"Salt Passage":"10%",
"Recovery":"59%",
"Concentration Factor":"2.43",
"status":"critical",
"Flow Alarm":"High Flow"
},
[
{
"Estimated Cost":"USD 15",
"AssetName":"RO2500AS1",
"Description":"Pump Maintenance",
"Index":"1",
"Type":"Service",
"DeadLine":"13 November 2013"
},
{
"Estimated Cost":"USD 35",
"AssetName":"RO2500AS1",
"Description":"Heat Sensor",
"Index":"2",
"Type":"Replacement",
"DeadLine":"26 November 2013"
},
{
"Estimated Cost":"USD 35",
"AssetName":"RO2550AS1",
"Description":"Heat Sensor",
"Index":"3",
"Type":"Replacement",
"DeadLine":"26 November 2013"
},
{
"Estimated Cost":"USD 15",
"AssetName":"RO2550AS1",
"Description":"Pump Maintenance",
"Index":"4",
"Type":"Service",
"DeadLine":"13 November 2013"
},
{
"Estimated Cost":"USD 15",
"AssetName":"RO3000AS1",
"Description":"Pump Maintenance",
"Index":"5",
"Type":"Service",
"DeadLine":"13 November 2013"
},
{
"Estimated Cost":"USD 35",
"AssetName":"RO3000AS1",
"Description":"Heat Sensor",
"Index":"6",
"Type":"Replacement",
"DeadLine":"26 November 2013"
}
]
]
I need to access it in javascript.
The following code is not working:
var jsonobjstr = JSON.parse(jsonOutput);
alert ("asset: "+jsonobjstr.asset);
Because the entire JSON is contained in an array.
alert("asset: "+jsonobjstr[0].asset);
http://jsfiddle.net/ExplosionPIlls/yHj5X/2/
In javascript
var somename = []; means a new array and;
var somename = {}; means a new object.
Therefore if some json starts with a [] means it is a array of objects, and if it starts with {} means it is a object.
Your json starts with [], therefore it is a array of objects, so you need to access each object by doing:
json[n].asset for each position of the array (where n is a integer).
BUT:
Your JSON is weird. Looks like you will always have a array with one element (if true, the json should start with {}.
LIKE:
{
"id":
{
"code":1381823399000
},
"asset":"RO2550AS1",
"history":
[
{
"value":"USD 15"
},
{
"value":"USD 15"
},
{
"value":"USD 15"
}
]
}
Here you can do:
thing.id.code
thing.asset
thing.history[0].value
thing.history[1].value

flattening json to csv format

i am trying to convert a json value to a flat csv based on the field that is selected by user . My json looks like
var data = {
"_index": "test",
"_type": "news",
"_source": {
"partnerName": "propertyFile 9",
"relatedSources": "null",
"entityCount": "50",
"Categories": {
"Types": {
"Events": [{
"count": 1,
"term": "Time",
"Time": [{
"term": "Dec 9",
"Dec_9": [{
"count": 1,
"term": "2012"
}]
}]
}, {
"count": 4,
"term": "News",
"News": [{
"term": "Germany",
"Germany": [{
"count": 1,
"term": "Election"
}],
"currency": "Euro (EUR)"
}, {
"term": "Egypt",
"Egypt": [{
"count": 1,
"term": "Revolution"
}]
}]
}]
}
}
}};
Ive been able to collect the values of all occurences and store it as a csv, but I want to save the details from the root itself..
If I select Time, the csv output should look like,
"test", "news", "propertyFile 9","null", "50", "Events": "Time", "Dec 9", "2012"
Is it possible to flatten the json.. I will add the json fiddle link to show where Ive reached with this thing..
http://jsfiddle.net/JHCwM/
Here is an alternative way to flatten an object into key/value pairs, where the key is the complete path of the property.
let data = {
pc: "Future Crew",
retro: {
c64: "Censor Design",
amiga: "Kefrens"
}
};
let flatten = (obj, path = []) => {
return Object.keys(obj).reduce((result, prop) => {
if (typeof obj[prop] !== "object") {
result[path.concat(prop).join(".")] = obj[prop];
return result;
}
return Object.assign(result, flatten(obj[prop], path.concat(prop), result));
}, {});
}
console.log(
flatten(data)
);
Your data value is not a JSON (string) - it's an object. There are many ways to 'flatten' this object, may be this little function might be helpful:
var recMap = function(obj) {
return $.map(obj, function(val) {
return typeof val !== 'object' ? val : recMap(val);
});
}
And here's how it can be used. )
There is a npm lib just for this with a lot of options: https://mircozeiss.com/json2csv/
# Global install so it can be called from anywhere
$ npm install -g json2csv
## Generate CSV file
$ json2csv -i data.json -o out.csv --flatten-objects
Try looking here:
http://www.zachhunter.com/2011/06/json-to-csv/
and here:
How to convert JSON to CSV format and store in a variable
Try the following :
http://codebeautify.org/view/jsonviewer
Use Export to CSV button
Check this out to flatten the Json
// Convert Nested Json to Flat Json
// Check the final json in firebug console.
var fullData = {"data":[{"Vehicle":"BMW","Date":"30, Jul 2013 09:24 AM","Location":"Hauz Khas, Enclave, New Delhi, Delhi, India","Speed":42,"Children":[{"Vehicle":"BMW","Date":"30, Jul 2013 09:24 AM","Location":"Hauz Khas, Enclave, New Delhi, Delhi, India","Speed":42,"Children":[{"Vehicle":"BMW","Date":"30, Jul 2013 09:24 AM","Location":"Hauz Khas, Enclave, New Delhi, Delhi, India","Speed":42,"Children":[]}]},{"Vehicle":"Honda CBR","Date":"30, Jul 2013 12:00 AM","Location":"Military Road, West Bengal 734013, India","Speed":0,"Children":[]}]},{"Vehicle":"Honda CBR","Date":"30, Jul 2013 12:00 AM","Location":"Military Road, West Bengal 734013, India","Speed":0,"Children":[]},{"Vehicle":"Supra","Date":"30, Jul 2013 07:53 AM","Location":"Sec-45, St. Angel's School, Gurgaon, Haryana, India","Speed":58,"Children":[]},{"Vehicle":"Land Cruiser","Date":"30, Jul 2013 09:35 AM","Location":"DLF Phase I, Marble Market, Gurgaon, Haryana, India","Speed":83,"Children":[]},{"Vehicle":"Suzuki Swift","Date":"30, Jul 2013 12:02 AM","Location":"Behind Central Bank RO, Ram Krishna Rd by-lane, Siliguri, West Bengal, India","Speed":0,"Children":[]},{"Vehicle":"Honda Civic","Date":"30, Jul 2013 12:00 AM","Location":"Behind Central Bank RO, Ram Krishna Rd by-lane, Siliguri, West Bengal, India","Speed":0,"Children":[]},{"Vehicle":"Honda Accord","Date":"30, Jul 2013 11:05 AM","Location":"DLF Phase IV, Super Mart 1, Gurgaon, Haryana, India","Speed":71,"Children":[]}]}
var finalData = [];
loopJson(fullData.data);
function loopJson(data) {
$.each(data, function(i, e) {
if (e.Children.length>0) {
var ccd = e.Children;
delete e.Children;
finalData.push(e);
loopJson(ccd);
} else {
delete e.Children;
finalData.push(e);
}
});
}
console.log(finalData);
Here is Js fiddle link http://jsfiddle.net/2nwm43yc/

Categories