Find a "date" from a table - calendar

I want to create a "Table" which is like a calendar with all months and days from 1-31. But what I want to do is: If the user picks a months and a day it has to give you a number (not random) For example
Days | Ene | Feb | Mar
----------------------
1 | A1 | A4 | A7
---------------------
2 | A2 | A5 | A8
---------------------
3 | A3 | A6 | A9
---------------------
If the user write or pick Ene 1, he will get A1 or Feb 2, will get A5 (and so on). That's the questions, how can I build it? PHP? Javascript? Java? Using SQL/DataBases?

tl;dr
map.get( Month.FEBRUARY ).get( 2 - 1 )
A5
Java
Month enum
First, you should know that Java has pre-defined a set of 12 objects for the months, in the Month enum. By the way, the enum facility in Java is much more powerful and flexible than is usual in most languages; you may want to learn more.
By the way, you can ask the Month class to automatically localize the name of the month via the getDisplayName method.
List
You numbers happen to be 1, 2, 3, so we can use those to access a List.
Unfortunately, access into a List is only provided as an index, meaning 0-based counting (an unfortunate hangover from the early days of programming). So we must subtract one from the day-of-month. For example, for the 1st, use 0, for the 2nd, use 1.
Map
We can map each month to its list of values using a Map.
Collection literals
Java 9 brings handy new Map.ofEntries and List.of methods for concisely generating unmodifiable collections.
Map< Month, List< String > > map =
Map.ofEntries(
entry( Month.JANUARY , List.of( "A1" , "A2" , "A3" ) ) , // This syntax requires at top: import static java.util.Map.entry ;
entry( Month.FEBRUARY , List.of( "A4" , "A5" , "A6" ) ) ,
entry( Month.MARCH , List.of( "A7" , "A8" , "A9" ) )
)
;
Accessing Map and List
Try it out. Simulate the user’s input of a month and day.
Month m = Month.FEBRUARY;
int dayOfMonth = 2;
Or get the month by number, 1-12 for January-December.
Month m= Month.of( 2 );
Access our Map to get that month’s List. Passing a Month object gets us back the List object we had put into the map.
List< String > list = map.get( m );
Access that List to get our desired String, such as A5.
String result = list.get( dayOfMonth - 1 ); // Subtract one for zero-based index.
Or, combine those two lines into one, accessing both the Map and the List.
String result = map.get( m ).get( dayOfMonth - 1 ); // One-liner, alternative.
A5
Let’s see all that code together.
Map< Month, List< String > > map = Map.ofEntries(
entry( Month.JANUARY , List.of( "A1" , "A2" , "A3" ) ) , // This syntax requires at top: import static java.util.Map.entry ;
entry( Month.FEBRUARY , List.of( "A4" , "A5" , "A6" ) ) ,
entry( Month.MARCH , List.of( "A7" , "A8" , "A9" ) )
);
Month m = Month.FEBRUARY; // Or, Month.of( 2 )
int dayOfMonth = 2;
List< String > list = map.get( m ); // Passing a `Month` object gets us back the `List` object we had put into the map.
String result = list.get( dayOfMonth - 1 ); // Subtract one for zero-based index counting to access `List`.
String result2 = map.get( m ).get( dayOfMonth - 1 ); // One-liner, alternative.

Related

Summation based on unique entries of two arrays | Speed Issue

I have 3 arrays of size 803500*1 with the following details:
Rid: It can contain any number
RidID: It contains elements from 1 to 184 in random order. Each element appears multiple times.
r: It contains elements 0,1,2,...12. All elements (except zero) appear nearly 3400 to 3700 times at random indices in this array.
Following may be useful for generating sample data:
Rid = rand(803500,1);
RidID = randi(184,803500,1);
r = randi(13,803500,1)-1; %This may not be a good sample for r as per previously mentioned details?
What I want to do?
I want to calculate the sum of those entries of Rid which correspond to each positive unique entry of r and each unique entry of RidID.
This may be clearer with the code which I wrote for this problem:
RNum = numel(unique(RidID));
RSum = ones(RNum,12); %Preallocating for better speed
for i=1:12
RperM = r ==i;
for j = 1:RNum
RSum(j,i) = sum(Rid(RperM & (RidID==j)));
end
end
Issue:
My code works but it takes 5 seconds on average on my computer and I have to do this calculation nearly a thousand times. If this time be reduced from 5 seconds to atleast half of it, I'll be very happy. But how do I optimize this? I don't mind if it is made better with vectorization or any better written loop.
I am using MATLAB R2017b.
You can use accumarray :
u = unique(RidID);
A = accumarray([RidID r+1], Rid);
RSum = A(u, 2:13);
This is slower than accumarray as suggested by rahnema, but using findgroups and splitapply may save memory.
In your example, there may be thousands of zero-valued elements in the resulting matrix, where a combination of RidID and r does not occur. In this case a stacked result would be more memory efficient, like so:
RidID | r | Rid_sum
-------------------------
1 | 1 | 100
2 | 1 | 200
4 | 2 | 85
...
This can be achieved with the following code:
[ID, rn, RidIDn] = findgroups(r,RidID); % Get unique combo ID for 'r' and 'RidID'
RSum = splitapply( #sum, Rid, ID ); % Sum for each ID
output = table( RidIDn, rn, RSum ); % Nicely formatted table output
% Get rid of elements where r == 0
output( output.rn == 0, : ) = [];
You could convert this to the same output as the accumarray method, but it's already a slower method...
% Convert to 'unstacked' 2D matrix (optional)
RSum = full( sparse( 1:numel(Ridn), 1:numel(rn), RSum ) );

How can I parse a cell array of date strings with irregular lengths in MATLAB?

I have a cell array of dates as strings (format: 'mm/dd/yyyy'), where the string length varies by cell entry from 8 to 10, depending on the date (e.g., n = 8 for '1/1/2015' and n = 10 for '10/10/2015'). I want to convert each cell array entry to its corresponding double as a datenum quantity. I've tried:
id = find(~cellfun( #isempty, regexp( dateList, '/', 'tokenExtents' ) ) );
and
id = find(~cellfun( #isempty, strfind( dateList, '/' ) ) );
but this isn't right. A snippet of the cell array is provided:
dateList = {'9/9/2016';
'9/10/2016';
'10/10/2016';
'10/11/2016'};
All you have to use is datenum, since it will accept a cell array of strings:
dateList = {'9/9/2016'; '9/10/2016'; '10/10/2016'; '10/11/2016'};
id = datenum(dateList);
And to confirm it worked:
>> datestr(id)
ans =
09-Sep-2016
10-Sep-2016
10-Oct-2016
11-Oct-2016
1) Extract each cell to 3 different blocks with strsplit: day,month and year
2) Use pad to make each block the same length (2 for day and month and 4 for year)
3) Join the string together with [D,'/',M,'/',Y] and you are able to run datenum without problem.
Edit 1: I think the other answer is far more easy, I didn't know datenum can take strings with slightly different foramt.

SPSS: using IF function with REPEAT when each case has multiple linked instances

I have a dataset as such:
Case #|DateA |Drug.1|Drug.2|Drug.3|DateB.1 |DateB.2 |DateB.3 |IV.1|IV.2|IV.3
------|------|------|------|------|--------|---------|--------|----|----|----
1 |DateA1| X | Y | X |DateB1.1|DateB1.2 |DateB1.3| 1 | 0 | 1
2 |DateA2| X | Y | X |DateB2.1|DateB2.2 |DateB2.3| 1 | 0 | 1
3 |DateA3| Y | Z | X |DateB3.1|DateB3.2 |DateB3.3| 0 | 0 | 1
4 |DateA4| Z | Z | Z |DateB4.1|DateB4.2 |DateB4.3| 0 | 0 | 0
For each case, there are linked variables i.e. Drug.1 is linked with DateB.1 and IV.1 (Indicator Variable.1); Drug.2 is linked with DateB.2 and IV.2, etc.
The variable IV.1 only = 1 if Drug.1 is the case that I want to analyze (in this example, I want to analyze each receipt of Drug "X"), and so on for the other IV variables. Otherwise, IV = 0 if the drug for that scenario is not "X".
I want to calculate the difference between DateA and DateB for each instance where Drug "X" is received.
e.g. In the example above I want to calculate a new variable:
DateDiffA1_B1.1 = DateA1 - DateB1.1
DateDiffA1_B2.1 = DateA1 - DateB2.1
DateDiffA1_B1.3 = DateA1 - DateB1.3
DateDiffA1_B2.3 = DateA1 - DateB2.3
DateDiffA1_B3.3 = DateA1 - DateB3.3
I'm not sure if this new variable would need to be linked to each instance of Drug "X" as for the other variables, or if it could be a single variable that COUNTS all the instances for each case.
The end goal is to COUNT how many times each case had a date difference of <= 2 weeks when they received Drug "X". If they did not receive Drug "X", I do not want to COUNT the date difference.
I will eventually want to compare those who did receive Drug "X" with a date difference <= 2 weeks to those who did not, so having another indicator variable to help separate out these specific patients would be beneficial.
I am unsure about the best way to go about this; I suspect it will require a combination of IF and REPEAT functions using the IV variable, but I am relatively new with SPSS and syntax and am not sure how this should be coded to avoid errors.
Thanks for your help!
EDIT: It seems like I may need to use IV as a vector variable to loop through the linked variables in each case. I've tried the syntax below to no avail:
DATASET ACTIVATE DataSet1.
vector IV = IV.1 to IV.3.
loop #i = .1 to .3.
do repeat DateB = DateB.1 to DateB.3
/ DrugDateDiff = DateDiff.1 to DateDiff.3.
if IV(#i) = 1
/ DrugDateDiff = datediff(DateA, DateB, "days").
end repeat.
end loop.
execute.
Actually there is no need to add the vector and the loop, all you need can be done within one DO REPEAT:
compute N2W=0.
do repeat DateB = DateB.1 to DateB.3 /IV=IV.1 to IV.3 .
if IV=1 and datediff(DateA, DateB, "days")<=14 N2W = N2W + 1.
end repeat.
execute.
This syntax will first put a zero in the count variable N2W. Then it will loop through all the dates, and only if the matching IV is 1, the syntax will compare them to dateA, and add 1 to the count if the difference is <=2 weeks.
if you prefer to keep the count variable as missing when none of the IV are 1, instead of compute N2W=0. start the syntax with:
If any(1, IV.1 to IV.3) N2W=0.

Using anonymous function rather than looping for summing up values in cell array

I have a matrix called data. It contains 3 columns, company name, company value & company currency, bit like below.
Name Value Currency
ABC 10 USD
MNO 5 JPY
PLM 3 USD
NJK 7 EUR
I need to sum the total value for each currency so my answer would look like below,
Currency Value
EUR 7
JPY 5
USD 13
I know I can do this using a loop but is it possible using an anonymous function and if so how?
Update - Extra information as original post lacked information
Below is my solution, which works. However I have seen people use cellFun or anonymous functions and fell like there is a more efficient way (and would to like alternative way) for problems of this nature
val = cell2mat(data(:, 2)); % double - value
sedols = data(:, [1 3]); % cell - name (1st column) and currency (2nd column)
ccy = unique(sedols(:, 2));
fx_exp = zeros(length(ccy(:, 1)), 1);
for n = 1 : length(ccy(:, 1))
index = strmatch(ccy(n, 1), sedols(:, 2));
fx_exp(n, 1) = sum(val(index));
end
Using cellfun or arrayfun is not more efficient than a simple loop. To take advantage of vectorization you need to work with pure double arrays.
Assuming your data is stored in a cell array, unique combined with accumarray is the way to go:
data = {
'ABC' 10 'USD'
'MNO' 5 'JPY'
'PLM' 3 'USD'
'NJK' 7 'EUR' };
[a,b,subs] = unique(data(:,3))
vals = [data{:,2}];
currsum = accumarray(subs,vals)
out = [data(b,3) num2cell(currsum)]
out =
'EUR' [ 7]
'JPY' [ 5]
'USD' [13]

postgres + json object to array

I would like to know if is possible to 'covnert' a json object to a json array to iterate over a mixed set of data.
I have two rows that look like
{Data:{BASE:{B1:0,color:green}}}
{Data:{BASE:[{B1:1,color:red},{B1:0,color:blue}]}}
I would like to extract the B1 val from all this rows, but I am a bit blocked :)
My first try was a json_extract_array, but it fails on the 1st row (not an array).
Then my second try was a json_array_length with a case, but that fails at the 1st row (not array)
Can I handle this situation in any way?
Basically I need to extract all the rows where B1 > 0 in one of the json array (or object) and maybe return the node that contains B1 > 0.
Your main problem is you mix the data types under the json -> 'Data' -> 'BASE' path, which cannot be handled easily. I could come up with a solution, but you should fix your schema, f.ex. to only contain arrays at that path.
with v(j) as (
values (json '{"Data":{"BASE":{"B1":0,"color":"green"}}}'),
('{"Data":{"BASE":[{"B1":1,"color":"red"},{"B1":0,"color":"blue"}]}}')
)
select j, node
from v,
lateral (select j #> '{Data,BASE}') b(b),
lateral (select substring(trim(leading E'\x20\x09\x0A\x0D' from b::text) from 1 for 1)) l(l),
lateral (select case
when l = '{' and (b #>> '{B1}')::numeric > 0 then b
when l = '[' then (select e from json_array_elements(b) e where (e #>> '{B1}')::numeric > 0 limit 1)
else null
end) node(node)
where node is not null
SQLFiddle
To return the rows where at least one object has B1 > 0
select *
from t
where true in (
select (j ->> 'B1')::int > 0
from json_array_elements (json_column -> 'Data' -> 'BASE') s (j)
)
With a little help from the other answers here, I did this:
with v(j) as (
values (json '{"Data":{"BASE":{"B1":0,"color":"green"}}}'),
('{"Data":{"BASE":[{"B1":1,"color":"red"},{"B1":0,"color":"blue"}]}}')
)
select j->'Data'->'BASE'->>'B1' as "B1"
from v
where j->'Data'->'BASE'->>'B1' is not null
union all
select json_array_elements(j->'Data'->'BASE')->>'B1'
from v
where j->'Data'->'BASE'->>'B1' is null
Divided it into two queries, one which just fetches a single value if there is only one, and one that unwraps the array if there are multiple, utilizing that PostgreSQL returns null if you ask for the text of something that is an array. Then, I just unioned the result from the two queries, which resulted in:
------
| B1 |
------
| 0 |
| 1 |
| 0 |

Resources