How to create nested objects from MySQL query? - javascript

I have this dummy MySQL data:
id date (y/m/d) value
1 2022-1-1 random value
2 2022-2-5 random value
3 2022-3-3 random value
4 2022-4-6 random value
5 2022-5-11 random value
6 2022-6-7 random value
7 2022-7-16 random value
8 2022-8-4 random value
9 2022-9-7 random value
10 2022-10-8 random value
11 2022-11-4 random value
12 2022-12-9 random value
13 2023-1-2 random value
14 2023-2-4 random value
15 2023-3-22 random value
16 2023-4-5 random value
17 2023-5-8 random value
18 2023-6-19 random value
19 2023-7-12 random value
20 2023-8-4 random value
21 2023-9-2 random value
22 2023-10-10 random value
23 2023-11-21 random value
24 2023-12-27 random value
I want to achieve something like this:
[{
year:2022,
value:[
{
month:1,
value:[
{
day:1,
value:'random value'
}
]
},
{
month:2,
value:[
{
day:5,
value:'random value'
}
],
...
}
]
},{
year:2023,
value:[
...
]
}]
Is there anything that can sort something like this? I am using JavaScript, Node.js and I get an array of data like the dummy data from MySQL query. I have to sort it like this for frontend React.
I need something that is fast and not require a lot of processing because this operation will be done many times on the server.
Do you have any ideas?
Thank you in advance. :)

You could take an object for grouping and get a nested structure by taking parts of the date.
const
data = [{ id: 1, date: '2022-01-01', value: 'random value' }, { id: 2, date: '2022-02-05', value: 'random value' }, { id: 3, date: '2022-03-03', value: 'random value' }, { id: 4, date: '2022-04-06', value: 'random value' }, { id: 5, date: '2022-05-11', value: 'random value' }, { id: 6, date: '2022-06-07', value: 'random value' }, { id: 7, date: '2022-07-16', value: 'random value' }, { id: 8, date: '2022-08-04', value: 'random value' }, { id: 9, date: '2022-09-07', value: 'random value' }, { id: 10, date: '2022-10-08', value: 'random value' }, { id: 11, date: '2022-11-04', value: 'random value' }, { id: 12, date: '2022-12-09', value: 'random value' }, { id: 13, date: '2023-01-02', value: 'random value' }, { id: 14, date: '2023-02-04', value: 'random value' }, { id: 15, date: '2023-03-22', value: 'random value' }, { id: 16, date: '2023-04-05', value: 'random value' }, { id: 17, date: '2023-05-08', value: 'random value' }, { id: 18, date: '2023-06-19', value: 'random value' }, { id: 19, date: '2023-07-12', value: 'random value' }, { id: 20, date: '2023-08-04', value: 'random value' }, { id: 21, date: '2023-09-02', value: 'random value' }, { id: 22, date: '2023-10-10', value: 'random value' }, { id: 23, date: '2023-11-21', value: 'random value' }, { id: 24, date: '2023-12-27', value: 'random value' }],
keys = ['year', 'month', 'day'],
result = data
.reduce((r, { date, value }) => {
date.split('-').reduce(function(level, key, i, a) {
if (!level[key]) {
level[key] = { _: [] };
level._.push(i + 1 === a.length
? { [keys[i]]: key, value }
: { [keys[i]]: key, children: level[key]._ }
);
}
return level[key];
}, r);
return r;
}, { _: [] })
._;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Those look like dates. Think about date arithmetic:
'2020-01-01' + INTERVAL FLOOR(RAND() * 1000) DAY
will generate one random date within 1000 days after the start of 2020. (Note there may be dups, but they could be dealt with afterward.)
This technique will generate Jan 31, but not Feb 31. It looks like your approach leads to losing Jan 31 or creating Feb 31.
Also, your data looks like you want one day per month. Is that a requirement. If so, please state. (My technique does not lend itself to such.)

Related

How to filter one array with another array values and return a key value of the first array

I have 2 arrays with current week dates and investments with value and date. I want to return an array with the values that have corresponding dates between the 2 arrays.
My non-working solution is:
const daysOfWeek = [
"20-06-2022",
"21-06-2022",
"22-06-2022",
"23-06-2022",
"24-06-2022",
"25-06-2022",
"26-06-2022",
]
const investmentsData = [{
value: 0.77,
date: "21-06-2022"
},
{
value: 1.50,
date: "22-06-2022"
},
{
value: 0.80,
date: "20-06-2022"
},
{
value: 1.00,
date: "21-06-2022"
},
{
value: 0.77,
date: "20-06-2022"
},
{
value: 0.79,
date: "22-06-2022"
},
{
value: 0.73,
date: "18-06-2022"
},
{
value: 1.29,
date: "19-06-2022"
}
]
const result = investmentsData.flatMap((dayValue) => {
const getDayValue = daysOfWeek.filter((day) => {
return dayValue.date === day;
});
return getDayValue;
});
const filteredResult = result.filter((val) => !!val);
console.log(filteredResult)
// ["21-06-2022", "22-06-2022", "20-06-2022", "21-06-2022", "20-06-2022", "22-06-2022"]
When what I need is:
[0.77, 1.50, 0.80, 1.00, 0.77, 0.79]
Probably the filter inside the map is not the best option as it´s going to return the value of the first array (which is a date).
I also have the problem that result returns also the undefined. I then run filteredResult to remove all the undefined in the result. I guess this is a job that can be done with one function all together.
Take it step by step:
Filter investmentsData on whether or not daysOfWeek contains the date
From the filtered values, return the value.
const daysOfWeek = ["20-06-2022", "21-06-2022", "22-06-2022", "23-06-2022", "24-06-2022", "25-06-2022", "26-06-2022"];
const investmentsData = [
{ value: 0.77, date: "21-06-2022" },
{ value: 1.50, date: "22-06-2022" },
{ value: 0.80, date: "20-06-2022" },
{ value: 1.00, date: "21-06-2022" },
{ value: 0.77, date: "20-06-2022" },
{ value: 0.79, date: "22-06-2022" },
{ value: 0.73, date: "18-06-2022" },
{ value: 1.29, date: "19-06-2022" }
]
const result = investmentsData
.filter(d => daysOfWeek.includes(d.date))
.map(d => d.value);
console.log(result);

Trying to get full results using DayJs

I'm trying to get the full results of this code execution, Right now what I get is only the date's of all values, but I need it so that all columns are displayed, so name and date. Can anyone help?
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-23T22:00:00.000Z' }
]
let time = dayjs().format('YYYY-MM-DD')
let eyy = result.filter(item1 => !result.find(item2 => item1.name == item2.name && dayjs(item2.date).format('YYYY-MM-DD') == time))
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
The result.filter method can be simplified by removing the use of result.find, for example...
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-23T22:00:00.000Z' }
]
let time = dayjs().format('YYYY-MM-DD')
let eyy = result.filter(item => dayjs(item.date).format('YYYY-MM-DD') === time)
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
It's probably worth noting that depending where you are in the world the above will most likely not return anything because there are no dates matching today's date (May 24th).
From your comments it appears you want to modify the structure of the filtered results. To do this you can use the .map() method...
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-24T22:00:00.000Z' }
];
let time = dayjs().format('YYYY-MM-DD');
let eyy = result.map(item => {
return {
name: item.name,
date: dayjs(item.date).format('YYYY-MM-DD')
};
});
eyy = eyy.filter(item => item.date === time);
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>

Taking an array of transactions and summing values to respective dates. Conditionally

So I have an array of transactions that looks like this:
[
{
date: '22-03-2021,
amount: 2,
value: 10,
fees: 0.1,
type: "BUY"
transactionId: '21412412',
}
]
And what I want to do with the array is two things...
One is get an array of objects per date. Summing the value property of objects that are of type 'BUY' and deducting the value property from objects of type 'SELL'. Eventually I will need to deal with other transaction types, but not now...
Example: (you can see the value rise and fall, due to SELL and BUY both taking place)
[
{
date: "04-06-2021",
value: 20.0,
},
{
date: "05-06-2021",
value: 28.99,
},
{
date: "06-06-2021",
value: 47.99,
},
{
date: "07-06-2021",
value: 37.99,
},
{
date: "08-06-2021",
value: 42.29,
},
]
Two is pretty similar. I want to generate an array of objects per date but associated to a particular ticker.
Example: (value rises due to only BUY taking place)
[
{
TSLA: [
{
date: "04-06-2021",
value: 20.0,
},
{
date: "05-06-2021",
value: 23.99,
},
{
date: "06-06-2021",
value: 42.99,
},
{
date: "07-06-2021",
value: 47.29,
},
]
}
]
Here is what ive come up with so far:
const valueByDate = useMemo(
() =>
holdings
.map((data: any) => data)
.reduce((r: any, a: any) => {
// Find objects where ticker matches.
r[a.date] = r[a.date] || [];
// Push found object into array.
r[a.date].push({ type: a.type, value: a.value });
return r;
}, Object.create(null)),
[holdings],
);
// valueByDate creates an object like so...
let arr = {
'22-05-2021': [{ type: 'SELL', value: '9' }],
'22-06-2021': [{ type: 'SELL', value: '9' }],
'22-07-2021': [{ type: 'SELL', value: '9' }],
};
// Sum or Deduct VALUE per date depending on TYPE
const reduce = Object.values(valueByDate).forEach((element: any) =>
Object.values(element)
.flat()
.reduce((accumulator: any, currentValue: any) => {
if (currentValue.type == 'BUY') {
return (
parseFloat(accumulator) + parseFloat(currentValue.value)
);
} else if (currentValue.type == 'SELL') {
return (
parseFloat(accumulator) - parseFloat(currentValue.value)
);
}
}),
);
But I just have not been able to wrap my head around getting into the nested arrays and conditionally computing those values. Any insight would be a help.
Thank you
Those are the functions that I created:
type Transaction = {
date: string,
amount: number,
value: number,
fees: number,
type: "BUY" | "SELL",
transactionId: string
}
const transactions: Transaction[] = [
{
date: '22-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
{
date: '22-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "SELL",
transactionId: '21412412',
},
{
date: '22-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
{
date: '23-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
{
date: '23-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
{
date: '23-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "SELL",
transactionId: '21412412',
},
{
date: '23-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
{
date: '23-03-2021',
amount: 2,
value: 10,
fees: 0.1,
type: "BUY",
transactionId: '21412412',
},
]
type DatedTransactions = { [key: string]: Transaction[] }
function getValuesByDate(transactions: Transaction[]): DatedTransactions {
let result: { [key: string]: Transaction[] } = {}
transactions.forEach(transaction => {
result[transaction.date] ? result[transaction.date].push(transaction) : result[transaction.date] = [transaction]
})
return result
}
function getTotalValue(transactions: Transaction[]): number {
return transactions.reduce((prev, curr) => {
if (curr.type === "BUY") {
return prev + curr.value
}
return prev - curr.value
}, 0)
}
function getTotalValueForEveryDate(datedTransactions: DatedTransactions): { date: string, value: number }[] {
const result: { date: string, value: number }[] = []
Object.keys(datedTransactions).forEach(date => {
const datedValue = { date, value: getTotalValue(datedTransactions[date]) }
result.push(datedValue)
})
return result
}
console.log(getTotalValueForEveryDate(getValuesByDate(transactions)))
in order to accomplish also the last part just iterate for every ticker :)
let me know if there is something not clear

How can I map and Object with Arrays as values? [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
How to loop through a plain JavaScript object with the objects as members
(28 answers)
Closed 1 year ago.
Given the following array of objects with dates in UTC:
const Arr = [
{
"name": "Person 1",
"date": "2021-02-28T14:00:00.000+0000"
},
{
"name": "Person 2",
"date": "2021-02-28T19:15:00.000+0000"
},
{
"name": "Person 3",
"date": "2021-04-04T18:30:00.000+0000"
},
{
"name": "Person 4",
"date": "2021-05-11T19:00:00.000+0000"
},
{
"name": "Person 5",
"date": "2021-05-12T18:45:00.000+0000"
},
{
"name": "Person 6",
"date": "2021-05-11T19:00:00.000+0000"
},
{
"name": "Person 7",
"date": "2021-05-23T15:00:00.000+0000"
}
];
I grouped the items by date using reduce as described in the below code:
const eventDate = {};
Arr.reduce((groupByDate, event) => {
const date = event.date.split('T')[0];
if (!groupByDate[date]) {
groupByDate[date] = [];
}
groupByDate[date].push(event);
return groupByDate;
}, {});
Getting an object grouped by date (as key) and an array of objects (as values):
{
'2021-02-28': [
{ name: 'Person 1', date: '2021-02-28T14:00:00.000+0000' },
{ name: 'Person 2', date: '2021-02-28T19:15:00.000+0000' }
],
'2021-04-04': [ { name: 'Person 3', date: '2021-04-04T18:30:00.000+0000' } ],
'2021-05-11': [
{ name: 'Person 4', date: '2021-05-11T19:00:00.000+0000' },
{ name: 'Person 6', date: '2021-05-11T19:00:00.000+0000' }
],
'2021-05-12': [ { name: 'Person 5', date: '2021-05-12T18:45:00.000+0000' } ],
'2021-05-23': [ { name: 'Person 7', date: '2021-05-23T15:00:00.000+0000' } ]
}
So my doubt here is how can I loop through that new object in order to get something like this?
(date in UTC will be formatted and get only the time)
2021-02-28:
name: Person 1 time: 14:00
name: Person 2 time: 19:15
2021-04-04:
name: Person 3 time: 18:30
2021-05-11:
name: Person 4 time: 19:00
name: Person 6 time: 19:00
2021-05-12:
name: Person 5 time: 18:45
2021-05-23:
name: Person 7 time: 15:00
Thanks in advance!
I would use Object.entries() or Object.keys() on the top level object to loop over it (for example using forEach() or any other looping method):
Object.entries(data).forEach(([key, items]) => {
console.log(key);
items.forEach(item => {
console.log("name:", item.name, "date:", item.date)
})
})
Playround
Perhaps something like this?
const obj = {
'2021-02-28': [
{ name: 'Person 1', date: '2021-02-28T14:00:00.000+0000' },
{ name: 'Person 2', date: '2021-02-28T19:15:00.000+0000' }
],
'2021-04-04': [{ name: 'Person 3', date: '2021-04-04T18:30:00.000+0000' }],
'2021-05-11': [
{ name: 'Person 4', date: '2021-05-11T19:00:00.000+0000' },
{ name: 'Person 6', date: '2021-05-11T19:00:00.000+0000' }
],
'2021-05-12': [{ name: 'Person 5', date: '2021-05-12T18:45:00.000+0000' }],
'2021-05-23': [{ name: 'Person 7', date: '2021-05-23T15:00:00.000+0000' }]
}
const newObj = {}
const newSubObj = {}
for (const [key, value] of Object.entries(obj)) {
newObj[key] = []
newSubObj[key] = []
for (const item of value) {
const date = new Date(item.date)
const subDate = item.date.substr(11, 5)
const hours = date.getUTCHours()
const minutes = date.getUTCMinutes()
newObj[key].push({ name: item.name, time: `${hours}:${minutes}` })
newSubObj[key].push({ name: item.name, time: subDate })
}
}
console.log(newObj, newSubObj)
Assuming you want to console.log() the result this is how I will do it:
const obj = {
'2021-02-28': [
{ name: 'Person 1', date: '2021-02-28T08:00:00.000+0000' },
{ name: 'Person 2', date: '2021-02-28T19:15:00.000+0000' }
],
'2021-04-04': [ { name: 'Person 3', date: '2021-04-04T18:30:00.000+0000' } ],
'2021-05-11': [
{ name: 'Person 4', date: '2021-05-11T19:00:00.000+0000' },
{ name: 'Person 6', date: '2021-05-11T19:00:00.000+0000' }
],
'2021-05-12': [ { name: 'Person 5', date: '2021-05-12T18:45:00.000+0000' } ],
'2021-05-23': [ { name: 'Person 7', date: '2021-05-23T15:00:00.000+0000' } ]
}
const printObj = (obj) => {
Object.keys(obj).forEach(key => {
console.log(`${key}:`);
obj[key].forEach(val => {
const currentDate = new Date(val.date);
const currentDateHours = (currentDate.getUTCHours() < 10 ? '0' : '') + currentDate.getUTCHours();
const currentDateMinutes = (currentDate.getUTCMinutes() < 10 ? '0' : '') + currentDate.getUTCMinutes();
console.log(`name: ${val.name} time: ${currentDateHours}:${currentDateMinutes}`);
})
});
}
printObj(obj);
Note: getUTCHours() and getUTCMinutes() will not show two digit number in case of a leading 0, I took it into consideration.

Jquery fortune wheel getting wrong result

I am creating a fortune wheel using jquery and want to getting the exact number from the spinning wheel
Jquery I am using this in html
var prices = [{
name: '0'
}, {
name: '1'
}, {
name: '2'
}, {
name: '3'
}, {
name: '4'
}, {
name: '5'
}, {
name: '6'
}, {
name: '7'
}, {
name: '8'
}, {
name: '9'
}, {
name: '10'
}, {
name: '11'
}, {
name: '12'
}, {
name: '13'
}, {
name: '14'
}, {
name: '15'
}, {
name: '16'
}, {
name: '17'
}, {
name: '18'
}, {
name: '19'
}, {
name: '20'
}, {
name: '21'
}, {
name: '22'
}, {
name: '23'
}, {
name: '24'
}, {
name: '25'
}, {
name: '26'
}, {
name: '27'
}, {
name: '28'
}, {
name: '29'
}, {
name: '31'
}, {
name: '32'
}, {
name: '33'
}, {
name: '34'
}, {
name: '35'
}, {
name: '36'
}];
$(function() {
var $r = $('.roulette').fortune(prices);
var clickHandler = function() {
$('.spinner').off('click');
$('.spinner span').hide();
$r.spin().done(function(price) {
$('.price').text('You have: ' + price.name);
$('.spinner').on('click', clickHandler);
$('.spinner span').show();
});
};
$('.spinner').on('click', clickHandler);
});
I am not sure where I am going with this code. everytime its spin its give me incorrect result.Please May be I am confuse with the logic behind this spinning wheel. Please help me with this
Here is the live example of what i created so far. Please guide me what I have to do to get the accurate result
http://codepen.io/anon/pen/bWwVVj
The problem is because your prices array is in numerical order. It should be in the same order as the values in shown on the roulette wheel, like this:
var prices = [
{ name: 0 },
{ name: 26 },
{ name: 3 }
// ...
];
Updated Codepen
Also note that your array of objects with just one property is pretty redundant. You can just use an array of integers instead, like this:
var prices = [0, 26, 3, 35, 12, 28, 7, 29, 18, 22, 9, 31, 14, 20, 1, 33, 16, 24, 5, 10, 23, 8, 30, 11, 36, 13, 27, 6, 34, 17, 25, 2, 21, 4, 19, 15, 32];
Updated Codepen

Categories