How can I select the features based on propetry - javascript

How can I select the features from the property attributes of the feature ?

Have a look at Array.protoype.filter()
Ok, it's not pretty but it works;)
Create a filter function
function filterBy(element) {
return
element.properties.systemtime_start ==
getMonthFromEpoch(element.properties.systemtime_start);
}
Create a function to filter the month
function getMonthFromEpoch(time) {
var month = 'noMonthSet';
var tMonth = new Date(time).toLocaleDateString('en-US', {month: 'long'});
if (tMonth == 'January') {
month = time;
}
return month
}
Pass the part with the features of your object to the filter
var filterd = yourObject.features.filter(filterBy)
This will return a new array with objects matching to systemstartTime 'January'
One more thing. I would change your naming. Use system_time_start instead of system:time_start. Otherwise you won't be able this property via JS

Related

How to link multiple children item to a single parent item?

I have a list of dates with properties and method I create with :
New CalendarDate('2018-XX-XX')
And for each date, I have a list of hours. I would like each of my hour to reference one single date.
At the moment, the solution I came from seems... inadequate, and I would like to understand the proper way to do it. So for each hour I create a new instance of Hour and pass the newly created date. I.E :
Class CalendarDate {
dateString: string
constructor(date: string) {
this.dateString = date
}
getDate() {
return this.dateString
}
}
Class CalendarHour {
date: CalendarDate
constructor(date: CalendarDate) {
this.date = date
}
}
let date1 = new CalendarDate('2018-11-11')
let hour1 = new CalendarHour(date1)
let hour2 = new CalendarHour(date1)
I want to avoid creating a new CalendarDate for every CalendarHour, but I'd rather like each CalendarHour to refer to the same CalendarDate object. What would be a better approach than the one I came up with ?

Traversing an array of objects and adding to other array based on condition

I have an array containing the following objects.
var notTotal = [{"Year":2012,"Value":800579},
{"Year":2012,"Value":654090},
{"Year":2012,"Value":758092},
{"Year":2013,"Value":343928},...More objects.. ]
What im trying to do is traverse this array of objects where only one Year exists instead of multiple and to add up the Values for that year. Using the example above..
var total = [{"Year":2012,"Value":2556689},
//Total of first three 2012 assuming there isnt anymore 2012 in the array
{"Year":2013,"Value":343928},...]
I have tried something like the following:
for(var i = 0; i < notTotal.length; i++) {
if (total.includes(notTotal[i].Year || notTotal[i])) {
//Add the value of the year in notTotal array to the same year in total array
} else {
total.push(notTotal[i]); //add year and value if it does not exist to the total array
}
}
Apologies if this is a duplicate. It seems like a pretty specific question.
Thanks!
An easy solution would be to create an object, holding totals by year.
var totalByYear = {};
You can then loop over the array using notTotal.forEach or a for loop as you've shown, adding to the value of the relevant year inside the totalByYear object.
notTotal.forEach(function(ele) { totalByYear[ele.Year] += ele.Value });
This yields an object with year keys and total values, e.g. using your example:
{'2012': 2556689, '2013': 343928 /* other years */}
The desired format (for D3) can then be built from the totalByYear object (and the totals by year printed):
var totals = [];
for (year in totalByYear) {
console.log('Total for year ' + year + ' is ' + totalByYear[year]);
//Build the correctly formatted array
totals.push({ Year: year, Value: totalByYear[year]});
}
//Prints:
//Total for year 2012 is 2556689
//etc.etc.
The totals array will then have the desired format.
Great question! To explain what's happening in your if (total.includes(notTotal[i].Year || notTotal[i])) is that you are looking through your total array for either just the year, or just an existing notTotal[i] exactly as it is. So your loop is trying to find a value that's exactly 2012 or exactly "Year":2012,"Value":2556689. Ergo, if your total array looked like this:
[{"Year":2012, "Value": 12345}]
your for loop would not find it even though there is an object with 2012 as its year. As for how to fix this, take a look at this previous question!
How to determine if Javascript array contains an object with an attribute that equals a given value?
Hopefully that helps :)
var notTotal = [{"Year":2012,"Value":800579},
{"Year":2012,"Value":654090},
{"Year":2012,"Value":758092},
{"Year":2013,"Value":343928}]
var totalObj = notTotal.reduce((sum, obj) => {
sum[obj.Year] = sum[obj.Year] + obj.Value || obj.Value;
return sum;
}, {});
// convert total to the format you need;
var total = Object.entries(totalObj).map(([Year, Value]) => ({Year, Value}))
console.log(total);
one more solution :
function yearlyValueFilter(array){
var yearlyValue = {}
array.forEach( (obj) => { //litterate on the input
var year = obj.Year
var value = obj.Value
if((year in yearlyValue)){ //if the array with not duplicated years conatins the litteration year just plus that value
yearlyValue[year] += value
}else{ //if not conatins, it gets as a basic value
yearlyValue[year] = value
}
})
return yearlyValue
}
You could built a hash table:
var hash = {},total=[];
for(const {Year,Value} of notTotal){
if(hash[Year]){
hash[Year].Value+=Value;
}else{
total.push(hash[Year]={Year,Value});
}
}
In action
Note: object properties are normally not capitalized...
You could use a hash table and check if the year does not exist, then generate a new result set. Then update the total count.
var values = [{ Year: 2012, Value: 800579 }, { Year: 2012, Value: 654090 }, { Year: 2012, Value: 758092 }, { Year: 2013, Value: 343928 }],
hash = Object.create(null),
totals = [];
values.forEach(function (o) {
hash[o.Year] || totals.push(hash[o.Year] = { Year: o.Year, Value: 0 });
hash[o.Year].Value += o.Value;
});
console.log(totals);

Does moment.js comparing dates not work properly?

I am building a datatable and wish to compare a date string that is passed in, to todays date, and then do something based on the outcome (before today, same as today etc etc)
"createdRow": function (row, data, dataIndex) {
var formattedDate = moment().format("DD-MMM-YYYY");
var dateIncoming = moment(data.NextDue, 'DD-MMM-YYYY').format("DD-MMM-YYYY");
if (dateIncoming < formattedDate) {
dateDue = true;
}
if (dateDue === true && data.AssignedToName !== "With Caller") {
$(row).css({ "color": "red" });
}
}
So it is mainly working, but I have one record where the dateDue is 15-03-2017 and the formattedDate is also 15-03-2017, but the css on my row is still activating.
I would normally expect this to happen if a datetime was also involved, and I also have several other values where dateDue is 15-03-2017 and these filter correctly.
You can use isBefore and isAfter to compare moment objects istead of <.
Moreover you need to remove format() since it trasforms moment object in string, so, as stated in the comments, in your code you are comparing strings intead of moment/dates.
Your code will be:
"createdRow": function (row, data, dataIndex) {
var formattedDate = moment();
var dateIncoming = moment(data.NextDue, 'DD-MMM-YYYY');
if (dateIncoming.isBefore(formattedDate)) {
dateDue = true;
}
if (dateDue === true && data.AssignedToName !== "With Caller") {
$(row).css({ "color": "red" });
}
}

A better way than chaining _.groupBy?

When I do this I get an array which stores the data as grouped by the month and day of the date but not by the year (I am doing this to get maximum, minimum, and average values for each day there is data for)
The problem is that the array stores an array of 2-3 values for that day and month within the date which is the key value. Those 2-3 indices each have an array of length one that holds a reference to an object which has the actual data point (level) I need. The object contains three attributes, date, id (which is always null), and level which is a float.
I either need to find a way so those 2-3 indices hold the object directly, or find a way that _.each can access the level.
Any thoughts?
var groupedData = _.groupBy(data, "date");
var groupedLevels = _.groupBy(groupedData, function (points, date) {
var dateParsed = parseDate(date);
var month = dateParsed.getMonth();
var day = dateParsed.getDate();
var monthDay = month + "-" + day;
return monthDay;
});
_.each(groupedLevels, function (points, date) {
var levels = _.map(_.pluck(points, "level"), parseFloat);
minimum.push([ date, R.min(levels) ]);
maximum.push([ date, R.max(levels);
var averageLevel = R.sum(levels) / levels.length;
average.push([date, averageLevel]);
})
So the data, as is, which is the original input looks like this (a sample piece):
[ { date: "2009-01-01",
id: null,
level: "0.08",
},
// ...
]
Currently, groupedData is this:
{ "2009-01-01":
[ { date: "2009-01-01",
id: null,
level: "0.08"
}
],
// ...
}
groupedLevels looks like this, for example:
{ "0-1":
[ [ { date: "2009-01-01".
id: null,
level: "0.08"
}
],
// ...
],
// ...
}
I want to skip having all the arrays of length one and just have the object stored there.
I think you can fix the immediate issue by replacing this line:
var levels = _.map(_.pluck(points, "level"), parseFloat);
With this:
var levels = _.map(_.pluck(points[0], "level"), parseFloat);
...but I think the real problem might be that you're doing groupBy twice when you don't need to. This single groupBy ought to be equivalent, but without the extra nested array:
var groupedLevels = _.groupBy(data, function(item) {
var dateParsed = parseDate(item.date);
var month = dateParsed.getMonth();
var day = dateParsed.getDate();
return month + '-' + day;
});
With this, your each should work as expected.

Better data structure to handle this array

I have an array of data get from the server(ordered by date):
[ {date:"2012-8", name:"Tokyo"}, {date:"2012-3", name:"Beijing"}, {date:"2011-10", name:"New York"} ]
I'd like to :
get the name of the first element whose date is in a given year, for example, given 2012, I need Tokyo
get the year of a given name
change the date of a name
which data structure should I use to make this effective ?
because the array could be large, I prefer not to loop the array to find something
Since it appears that the data is probably already sorted by descending date you could use a binary search on that data to avoid performing a full linear scan.
To handle the unstated requirement that changing the date will then change the ordering, you would need to perform two searches, which as above could be binary searches. Having found the current index, and the index where it's supposed to be, you can use two calls to Array.splice() to move the element from one place in the array to another.
To handle searches by name, and assuming that each name is unique, you should create a secondary structure that maps from names to elements:
var map = {};
for (var i = 0, n = array.length; i < n; ++i) {
var name = array[i].name;
map[name] = array[i];
}
You can then use the map array to directly address requirements 2 and 3.
Because the map elements are actually just references to the array elements, changes to those elements will happen in both.
Assuming you are using unique cities, I would use the city names as a map key:
cities = {
Tokyo: {
date: "2012-8"
},
New York: {
date: "2011-10"
}
}
To search by date:
function byDate(date) {
for(el in cities) {
if(cities.hasOwnProperty(el) && cities[el].date === date)
return el;
}
}
Just for the record: without redesigning your date structure you could use sorting combined with the Array filter or map method:
function sortByDate(a,b){
return Number(a.date.replace(/[^\d]+/g,'')) >
Number(b.date.replace(/[^\d]+/g,''));
}
var example = [ {date:"2012-8", name:"Tokyo"},
{date:"2012-3", name:"Beijing"},
{date:"2011-10", name:"New York"} ]
.sort(sortByDate);
//first city with year 2012 (and the lowest month of that year)
var b = example.filter(function(a){return +(a.date.substr(0,4)) === 2012})[0];
b.name; //=> Beijing
//year of a given city
var city = 'Tokyo';
var c = example.filter(function(a){return a.city === city;})[0];
c.year; //=> 2012
//change year of 'New York', and resort data
var city = 'New York', date = '2010-10';
example = example.map(
function(a){if (a.name === city) {a.date = date;} return a;}
).sort(sortByDate);

Categories

Resources