Reading from an object - react-native

I want to retrieve the values of marked dates how can I get all the marked dates where marked value is true from this object:
alert(JSON.stringify(this.state._markedDates))
{"2018-09-26":{"marked":true}, "2018-09-27":{"marked":false}, "2018-09-29":{"marked":true}}
Expected Result :
{"2018-09-26","2018-09-29"}
I tried the following but datelist is still empty:
for(var i=0; i<this.state._markedDates.length ; i++)
{
if(this.state._markedDates[i].marked == true)
{
this.state.datesList.push(_markedDates[i])
}
}

let dates = {
"2018-09-26":{"marked":true},
"2018-09-27":{"marked":false},
"2018-09-29":{"marked":true}
}
let markedDates=[];
Object.keys(dates).map(date => {
if(dates[date].marked){ markedDates.push(date)}
})
console.log(markedDates)

There are different ways of approaching this, you could filter them for example as below:
let dates = ["2018-09-26":{"marked":true}, "2018-09-27":{"marked":false}, "2018-09-29":{"marked":true}];
let filtered = dates.filter( date => {
if(date.marked === true) {
return date;
}
});
// filtered = {"2018-09-26":{"marked":true}, "2018-09-29":{"marked":true}};
This is how you can get all of the dates where marked = true.
Then you can do
let keyNames = Object.keys(filtered);
console.log(keyNames); // Outputs ["2018-09-26","2018-09-29"]
As a for loop
let markedDates = [];
for(var i=0; i<this.state._markedDates.length; i++)
{
if(this.state._markedDates[i].marked === true)
{
markedDates.push(_markedDates[i])
}
}
this.setState({ObjectIWantToSet: markedDates})

let dates = []
let obj = {"2018-09-26":{"marked":true}, "2018-09-27":{"marked":false}, "2018-09-29":{"marked":true}}
for(date in obj)
{
if(a[date]["marked"])
{
dates.push(date)
}
}
console.log(dates)

Related

How to remove time component from date fields while exporting to excel using sheetjs

I am able to export a list of JSON objects to an excel file using sheetjs in angular. One of the requirements is, user should be able to sort and filter the date fields like below.
But as you can see, along with the date part, the time part also comes while filtering. Is there a way, I can remove the time part and still be able to do the filtering like above?
Here is my code.
exportToExcel(arrData: any[], fileName: string, formattingData: ExcelFormattingData = undefined) {
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(arrData, {cellDates: true, dateNF: this.userAuthToken.dateFormat});
if(formattingData != null) {
const range = XLSX.utils.decode_range(worksheet['!ref']);
for (let j = range.s.c; j <= range.e.c; j++) {
let ref_columnHeader = XLSX.utils.encode_cell({r:range.s.r, c:j});
let columnName = worksheet[ref_columnHeader].v;
if(formattingData.Values.includes(columnName)){
for(let i = range.s.r + 1; i <= range.e.r; ++i) {
let ref = XLSX.utils.encode_cell({r:i, c:j});
if(worksheet[ref] != null) {
worksheet[ref].t = 'd';
worksheet[ref].z = formattingData.Format;
}
}
}
}
}
const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
FileSaver.saveAs(blob, fileName);
}

Row Span AutoGrouping and Bug

I've created a plnkr to auto-group row-spans the way you would really expect it to work out of the box IMHO.
Anyhow... doing this surfaces an apparent bug... the rowSpan is not consistently applied to the grid.. if you scroll up and down, it sometimes applies, and sometimes does not.
In the screenshot below... you can see 'Aaron Peirsol' is spanning... but if I scroll up and down it might not span on him... not consistent.
Here 'Aaron Peirsol' is no longer spanning all 3 rows -- all I did was scroll up and back down
See this Sample
https://plnkr.co/edit/UxOcCL1SEY4tScn2?open=app%2Fapp.component.ts
Here I've added columndefs for the grouping
{
field: 'athlete',
rowSpan: params => params.data.groupCount,
cellClassRules: {
'cell-span': "data.isFirst && data.groupCount>1",
},
width: 200,
},
{field:'groupCount', width: 20}, /* included for debugging */
{field:'isFirst', width: 20}, /* included for debugging */
And here I'm doing the auto-grouping code:
onGridReady(params: GridReadyEvent) {
this.http
.get<any[]>('https://www.ag-grid.com/example-assets/olympic-winners.json')
.subscribe((data) => {
let groupKey = 'athlete';
let sorted = data.sort((a,b) => (a[groupKey] > b[groupKey]) ? 1 :
((b[groupKey] > a[groupKey]) ? -1 : 0));
let filtered = sorted.filter(x => {
return x[groupKey] < 'Albert' && x[groupKey];
});
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
let keyValue = x[key];
if (rv[keyValue] === undefined)
{
rv[keyValue] = 0;
}
if (keyValue) {
rv[keyValue] ++;
}
return rv;
}, {});
};
let grouped = groupBy(filtered, groupKey);
let prev = '';
for (let i=0; i<filtered.length; i++)
{
let keyValue = filtered[i][groupKey];
filtered[i]['groupCount'] = grouped[keyValue];
if (keyValue == prev)
{
filtered[i]['isFirst'] = false;
}
else
{
filtered[i]['isFirst'] = true;
}
prev = keyValue;
}
this.rowData = filtered});
}
OK, found the issue...
rowSpan function must only return a span count for the first row of the span...
every other row it must return 1
I've updated the plunker
public columnDefs: ColDef[] = [
{
field: 'athlete',
rowSpan: params => params.data.groupRowCount == 1 ? params.data.groupCount: 1, //THIS IS CRUCIAL.. only return count for first row
cellClassRules: {
'cell-span': "data.groupRowCount==1 && data.groupCount>1",
},
width: 200,
},

Expand Text of Compact Data

I am stuck with some data manipulation.
This is a small portion of the input data (df):
site=c("C000-C002","C420-C421,C424")
histology=c("9835-9836","9811-9812,9837")
category=c("Leukemia","Leukemia")
df=data.frame(site,histology,category)
And this is what I want the processed data to look like:
You may assume Site and Histology are both 4-digit after text splitting.
In case anyone is interested, the full data table is here
Please help with the text processing, or if anyone knows an existing processed package or database in a similar format as the image, that would be great too.
Thank you very much.
I don't know R language. So I tried with Javascript as following.
function mapStartEnd(start, end) {
let list = [];
let info = {};
const siteStart = start.match(/([A-Z])(\d{3})/);
if (siteStart) {
const siteEnd = end.match(/([A-Z])(\d{3})/);
info = {
type: "site",
prefix: siteStart[1],
numLength: 3,
from: parseInt(siteStart[2], 10),
to: parseInt(siteEnd[2], 10),
};
}
const histologyStart = start.match(/\d{4}/);
if (histologyStart) {
const histologyEnd = end.match(/\d{4}/);
info = {
type: "histology",
prefix: "",
numLength: 4,
from: parseInt(histologyStart[0], 10),
to: parseInt(histologyEnd[0], 10),
};
}
const categoryStart = start.match(/[A-Z][a-z]+/);
if (categoryStart) {
const categoryEnd = end.match(/[A-Z][a-z]+/);
info = {
type: "category",
prefix: "",
numLength: 0,
from: categoryStart[0],
to: categoryEnd[0],
};
}
if (!info.numLength) {
list = [info.from, info.to];
} else {
for (let i = info.from; i <= info.to; i++) {
list.push(info.prefix + i.toString().padStart(info.numLength, "0"));
}
}
return list;
}
function c(list) {
return list.map((list2) => {
return list2.split(",").reduce((prev, cur) => {
const [start, end] = cur.split("-");
if (!end) prev.push(start);
else prev = [...prev, ...mapStartEnd(start, end)];
return prev;
}, []);
});
}
function map3(sites, histologys, categorys) {
let list = [];
for (let i = 0; i < sites.length; i++) {
const site = sites[i];
for (let j = 0; j < histologys.length; j++) {
const histology = histologys[j];
for (let k = 0; k < categorys.length; k++) {
const category = categorys[k];
// JSON format
// list.push({ site, histology, category });
// CSV format
list.push(`${site},${histology},${category}`);
}
}
}
return list;
}
function frame(sites, histologys, categorys) {
let list = [];
for (let i = 0; i < sites.length; i++) {
const site = sites[i];
const histology = histologys[i];
const category = categorys[i];
list = [...list, ...map3(site, histology, category)];
}
return list;
}
const site = c(["C000-C002", "C420-C421,C424"]);
const histology = c(["9835-9836", "9811-9812,9837"]);
const category = c(["Leukemia", "Leukemia"]);
const df = frame(site, histology, category);
console.log(df);
Result:
[
"C000,9835,Leukemia",
"C000,9836,Leukemia",
"C001,9835,Leukemia",
"C001,9836,Leukemia",
"C002,9835,Leukemia",
"C002,9836,Leukemia",
"C420,9811,Leukemia",
"C420,9812,Leukemia",
"C420,9837,Leukemia",
"C421,9811,Leukemia",
"C421,9812,Leukemia",
"C421,9837,Leukemia",
"C424,9811,Leukemia",
"C424,9812,Leukemia",
"C424,9837,Leukemia"
]
https://jsfiddle.net/dnu2g0vr/

Highcharts with decrease order in each interval

Is it possible to create a graph sorted in each time interval using Highcharts?
For expample, in this picture for January data will be in order: New York, Tokyo, London, Berlin. The same for each months - data should be shown decrease order
Highcharts doesn't have a built-in function to do that, but for example you can use the render event and organize columns, by changing their positions in the way you need.
events: {
render: function() {
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/tnrch8v1/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
#ppotaczek Thank You for help a lot! I solve my issue, but i had to make some changes to your code:
events: {
render: function() {
if (this.series.length === 0) return
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
},
}
So i changed:
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
to:
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});

It is corret usage to create a tab for mithril?

I want to create a simple Tab but I think it is strange for my using:
var root = document.body
var index = {
view: () => index.html,
html: m('div', { id: 'div1' }, [
[
(function () {
let value = ["A", "B", "C", "D"]
let output = []
for (let i = 0; i < 4; i++) {
output.push(m('input', {
class: (function () {
if (i == 0) return "onit"
})(),
type: 'button',
value: value[i],
onclick: function () {
let div1 = document.getElementById("div1")
let btn = div1.getElementsByTagName("input")
let div1_div = div1.getElementsByTagName("div")
let _this = this
let num = (function () {
for (let i = 0; i < btn.length; i++) {
if (btn[i] == _this) {
return i
}
}
})()
for (let i = 0; i < btn.length; i++) {
btn[i].className = ""
}
this.className = "onit"
for (let i = 0; i < div1_div.length; i++) {
div1_div[i].setAttribute("style", "dispaly:none")
}
div1_div[num].setAttribute("style", "display:block")
}
}))
}
return output
})()
],
[
(function () {
let arr = ["aaa", "bbb", "ccc", "ddd"]
let output = []
for (let i = 0; i < 4; i++) {
output.push(m("div", { style: (the => i == 0 ? "display:block" : undefined)() }, arr[i]))
}
return output
})()
]
])
}
m.route(root, "/index", {
"/index": index
})
Is there any other simple way to achieve this?
If I click the button, the style of button will change and the display of all "div" will be changed. Screenshot
In mithril.js views you can only use expressions, for-loops, ifs and so on are no expressions and only possible the way you did it. Nevertheless there are other ways to achieve this
Loops can be achieved using the functional counterparts
let values = ["A", "B", "C", "D"]
let output = []
function(){
for (let i = 0; i < 4; i++) {
output.push(m('span', value)
}
return output
}()
can be written as
values.map(value => m('span', value)
if-Statements can be written using the ternary expression
function() {
if (condition) {
return 'this'
} else {
return 'that'
}
}()
just use
condition ? 'this' : 'that'
You can also use view functions if your view code gets to deeply nested and you need custom logic:
function someOtherView(someData) {
if (someData.shouldBeShown) {
return someData.text
}
}
function someView() {
...
someOtherView(someData)
...
}
This also makes your views more readable.