How to get a new array from an array with nested objects? - javascript

I have the below array:
var data = [
{ "id":"id1", "key":"2020-07-15T06:32:44.08Z", "value":["E19","on"] },
{ "id":"id2", "key":"2020-07-15T06:32:44.08Z", "value":["E20","on"] },
{ "id":"id3", "key":"2020-07-15T06:32:44.08Z", "value":["E21","off"] },
{ "id":"id1", "key":"2020-07-15T06:33:44.08Z", "value":["E19","on"] },
{ "id":"id4", "key":"2020-07-15T06:34:44.08Z", "value":["E19","faulty"] },
{ "id":"id5", "key":"2020-07-15T06:35:44.08Z", "value":["E19","on"] }
];
I want this data to be converted to the below form to be used on Google charts:
var expectedData = [
["time","on","off","faulty"],
["06:32:44",2,1,0],
["06:33:44",2,1,0], //here the count is same because E19 is only records for this time which is
//already marked as 'on' in the before time stamp. Hence no change is required.
["06:34:44",1,1,1], //E19 has been changed to 'faulty', hence 'on' is reduced by 1 and 'faulty'
//increased by 1
["06:35:44",2,1,0] //E19 is changed back to 'on' hence 'on' is increased by 1 and 'faulty'
//reduced by 1
];
Can someone please help me with javascript code to sort this data to be used in my React Google charts?
I have written the below code so far:
const data = [
{ "id":"id1", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/19","on"] },
{ "id":"id2", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/20","on"] },
{ "id":"id3", "key":"2020-07-15T06:32:44.08Z", "value":["GigabyteEthernet4/0/21","off"] },
{ "id":"id1", "key":"2020-07-15T06:33:44.08Z", "value":["GigabyteEthernet4/0/19","on"] },
{ "id":"id4", "key":"2020-07-15T06:34:44.08Z", "value":["GigabyteEthernet4/0/19","faulty"] },
{ "id":"id5", "key":"2020-07-15T06:35:44.08Z", "value":["GigabyteEthernet4/0/19","on"] }
];
// var poeObj = new Object();
let t;
var newArray= [];
var newData = data.map((item,el)=>{
t= new Date(item.key);
var poeObj = Object.assign({},el)
poeObj.time= t.toLocaleTimeString();
poeObj.intfName= item.value[0];
poeObj.state= item.value[1];
if(poeObj.intfName)
console.log(poeObj);
return poeObj;
})
console.log(newData)
var newData1 = [
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"},
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/20", state: "on"},
{time: "12:02:44 PM", intfName: "GigabyteEthernet4/0/21", state: "off"},
{time: "12:03:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"},
{time: "12:04:44 PM", intfName: "GigabyteEthernet4/0/19", state: "faulty"},
{time: "12:05:44 PM", intfName: "GigabyteEthernet4/0/19", state: "on"}
]
var uniqueData = newData1.reduce((arr,item)=>{
var newArr = [];
newArr.push(item.time, item.intfName, item.state);
console.log(newArr)
arr.push(newArr)
return arr;
},[])
console.log(uniqueData)
//uniqueData= [
["12:02:44 PM", "GigabyteEthernet4/0/19", "on"],
["12:02:44 PM", "GigabyteEthernet4/0/20", "on"],
["12:02:44 PM", "GigabyteEthernet4/0/21", "off"],
["12:03:44 PM", "GigabyteEthernet4/0/19", "on"],
["12:04:44 PM", "GigabyteEthernet4/0/19", "faulty"],
["12:05:44 PM", "GigabyteEthernet4/0/19", "on"]
];
After all these code, I have got the formatted array as the above 'uniqueData'. But not sure if this is the efficient way. Although, I idn't reach my final expected output which is 'expectedData' mentioned in the begining. Can some one please advise me on this?

You can transform the content of your item in an array by using Array map function.
If I have the following:
var data = [
{ "id":"1", "title":"Lorem ipsum" },
{ "id":"2", "title":"Test title" },
{ "id":"3", "title":"another title" },
];
I can do:
// .map will traverse each item and we pass a function on how we want to deal with new item structure
data.map((item) => {
// I will convert individual item to this format: Array[id, title]
return [item.id, item.title]
})
This will return
[
[1, "Lorem ipsum"],
[2, "Test title"],
[3, "another title"],
]
In your question you have a different item structure in your array ["time","on","off","faulty"]
by getting the output from .map you just append using .splice ["time","on","off","faulty"] from your .map result.
// This will append ["time","on","off","faulty"] in the first index of array
result.splice(0, 0, ["time","on","off","faulty"])
Using reduce is also possible
I can do:
// Reduce also works by merging items, it can take two parameters (function, initial value)
data.reduce((accumulated, currentItem) => {
accumulated.push([currentItem.id, currentItem.title])
}, [["time","on","off","faulty"]])
This will have similar output with .map, the difference is you can put ahead the ["time","on","off","faulty"] in your new array without doing splice.

Related

Remove " " from keys when PHP associative array in parsed through json_encode

I am trying to supply some data to a Javascript Function but right now i am unable to convert it to desired format.
The Correct Format that is Working is below.
const eventsArr = [
{
day: 1,
month: 1,
year: 2023,
events: [
{
title: "asdEvent 1 lorem ipsun dolar sit genfa tersd dsad ",
time: "10:00 AM",
}
],
},
{
day: 13,
month: 11,
year: 2022,
events: [
{
title: "Event 2",
time: "11:00 AM",
},
],
},
];
The format is am being able to produce is the following.
const eventsArr = [
{
"day": "18",
"month": "2",
"year": "2023",
"events": [
{
"title": "Feb 18th Event and Updated From Databae",
"time": "05:10"
}
]
}
The Only difference between two javascript objects/arrays is that my version has "" around the keys and the working format does not have "" around the keys.
My Server Side PHP Code where i am using json_encode
$events = [];
foreach($db_data['CalendarEvent'] as $event)
{
$single_event = array(
'day'=>$event->ce_day,
'month'=>$event->ce_month,
'year'=>$event->ce_year,
'events'=>array(
array(
'title'=> $event->ce_title,
'time'=> $event->ce_time_from,
)
)
);
$events[] = $single_event;
}
$db_data['all_events'] = json_encode($events , JSON_PRETTY_PRINT);
Can somebody help me in this? How can i produce the required format (without "" around the keys in javascript). What i am doing wrong?
Thanks in Advance

how to change JSON Nested array property "project_id" with "project_name"

Trouble:
[
{
"project_id": 1,
"project_name": "CDP",
"role": "PL"
},
{
"project_id": 2,
"project_name": "Admincer",
"role": "PM"
},
I want to add the "project_id" property from the above three properties to another array using some method.
My idea is: 1. First of all, if I could copy the "project_id" property of this array to the second Nested JSON array, it would be fine.
What I looked up:
const obj = {
"project_id": 1,
"project_name": "CDP",
"role": "PL"
};;
const objCopy = {
"start_time": "09:00:00",
"end_time": "18:00:00",
"rest_time": "01:00:00",
"worked_time": "08:00:00",
"is_wfh": true,
"id": 1, 1,
"work_day_id": 45,
"time_cards": [
{
... obj
}
]
};;
console.log (objCopy);
I found that I could copy it this way.
I tried the above code in Chrome Console.
The array was copied, but the entire object was copied. I just want to copy the properties of project_id.
I want to create a new property called "prj_name" in this array and display only that property in Vuetify.
async fetchWorkerTimeCard() {
try {
this.worker_data = []
await this.$axios.$get('/worker_time_card', {
params: {
work_date: this.calendarVal
}
}).then(data => {
this.worker_data = data
})
var projects = await this.fetch_worker_projects()
console.log(projects)
} catch (error) {
console.log(error)
this.worker_data = []
}
},
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.5/vue.js"></script>
<v-card>
<v-data-table v-if="worker_data.time_cards" :headers="headers2" :items="worker_data.time_cards"></v-data-table>
</v-card>
You can simply change your object data like any other object in JS.
const obj = {
"project_id": 1,
"project_name": "CDP",
"role": "PL"
};
const objCopy = {
"start_time": "09:00:00",
"end_time": "18:00:00",
"rest_time": "01:00:00",
"worked_time": "08:00:00",
"is_wfh": true,
"id": 1,
"work_day_id": 45
}
console.log({...obj, ...objCopy})
This will create 1 object that merged.
Or if you just want to project_id value then just change it like:
objCopy.project_id = obj.project_id
If I'm understanding your first question correctly, you might be interested in the map function, which allows you to create a new array from an existing array. So, for example, if the first snippet you posted is an array of objects we call projects, you could use:
var projectIds = projects.map(p => p.project_id), where projectIds would now be an array of just project ids.
It seems like you might be asking more than this though, so I second Bravo's request for more clarification/reorganization in your question.
I'm not pretty sure if you want either of the following results:
{
"start_time": "09:00:00",
"end_time": "18:00:00",
"rest_time": "01:00:00",
"worked_time": "08:00:00",
"is_wfh": true,
"id": [
1,
1
],
"work_day_id": 45,
"time_cards": [
{
"project_id": 1
},
{
"project_id": 2
}
]
}
or this
{
"start_time": "09:00:00",
"end_time": "18:00:00",
"rest_time": "01:00:00",
"worked_time": "08:00:00",
"is_wfh": true,
"id": [
1,
1
],
"work_day_id": 45,
"time_cards": [
"project_id": [1, 2]
}
In case you need the first scenario, the following code may help you:
// This function return an array with: [{project_id: Number}]
function onlyIds(obj) {
const ids = [];
// Iterate the obj Array
obj.forEach(element => {
// Push a new JSON: "{project_id: 1}" or whatever
ids.push({ project_id: element.project_id });
});
// return an array that only contains the project_id
return ids;
}
const obj = [
{
project_id: 1,
project_name: 'CDP',
role: 'PL',
},
{
project_id: 2,
project_name: 'Admincer',
role: 'PM',
},
];
const objCopy = {
start_time: '09:00:00',
end_time: '18:00:00',
rest_time: '01:00:00',
worked_time: '08:00:00',
is_wfh: true,
id: [1, 1],
work_day_id: 45,
time_cards: onlyIds(obj),
};
console.log(onlyIds(obj));
console.log(objCopy);
I'm pretty sure there should be any more elegant/optimal way (as using any kind of higher-order function I may be missing right now) but as far as I understood, this should do the job.

How to filter JSON data from API by date range in JavaScript

I want to filter the below JSON data by start date and end date, it should return the data between start date and end date, I tried to achieve using below code, but I'm doing wrong something to filter. I'm new to front end technologies like JavaScript. It would be appreciated if someone can correct me what I'm doing wrong here:
The API data is like that seen below
{
"rec_id": 1,
"emp_id": 1,
"date": "Jan 22, 2020",
"time_in": "09:20",
"time_out": "19:56",
"total_hours": 10.6,
"weekday": 4,
"name": "Carlina Dahlberg",
"gender": "Female",
"designation": "Supervisor",
"department": "Production",
"calculate": "",
"basic_salary": 20000,
"per_day_salary": 1000
},
{
"rec_id": 2,
"emp_id": 2,
"date": "Jan 22, 2020",
"time_in": "08:33",
"time_out": "13:16",
"total_hours": 4.72,
"weekday": 4,
"name": "Brenden Greenacre",
"gender": "Male",
"designation": "Executive",
"department": "Marketing",
"calculate": "",
"basic_salary": 25000,
"per_day_salary": 1250
},
This is my code file
async function getData(){
let myData = await fetch("http://34.198.81.140/attendance.json")
.then((respose) => {
return respose.json()
})
.then((data) => {
return data;
});
let startDate ="Feb 1, 2020";
let endDate = "Feb 29, 2020";
let result = myData.filter((data) => {
return data.date >= startDate && data.date <=endDate;
})
console.log(result);
}
getData()
The data get filtered but not as per requirement, please see the screen shot of console output. In the screen shot the Data come from 1 feb to 29 Feb but, the Data from 2 Feb to 9 Feb whole data is skip by filter function.
You can use Urnary (+) operator, with new Date() to create a timestamp, and then you can compare the timestamps to get desired result.
async function getData() {
/*
let myData = await fetch("http://34.198.81.140/attendance.json")
.then((respose) => {
return respose.json()
})
.then((data) => {
return data;
});*/
// For Testing Purposes only (data modified)
let myData = [{
"rec_id": 1,
"emp_id": 1,
"date": "Jan 22, 2020",
"time_in": "09:20",
"time_out": "19:56",
"total_hours": 10.6,
"weekday": 4,
"name": "Carlina Dahlberg",
"gender": "Female",
"designation": "Supervisor",
"department": "Production",
"calculate": "",
"basic_salary": 20000,
"per_day_salary": 1000
},
{
"rec_id": 2,
"emp_id": 2,
"date": "Feb 5, 2020",
"time_in": "08:33",
"time_out": "13:16",
"total_hours": 4.72,
"weekday": 4,
"name": "Brenden Greenacre",
"gender": "Male",
"designation": "Executive",
"department": "Marketing",
"calculate": "",
"basic_salary": 25000,
"per_day_salary": 1250
}
]
let startDate = +new Date("Feb 1, 2020");
let endDate = +new Date("Feb 29, 2020");
let result = myData.filter((data) => {
return +new Date(data.date) >= startDate && +new Date(data.date) <= endDate;
})
console.log(result);
}
getData()
You need to parse the date into something you can compare dates with.
There are a few options in front of you for that.
Rely on Date.Parse(), a bad idea ref. (mdn)
Use an alternative date library. A simple google search should reveal some.
After parsing the date, you can use the same logic that you are currently using.
you can do it through converting the strings of number into numbers. afterwards try comparing them with each other.
You can use JS libraries such as Moment.js or Dayjs as well to get around it.look through their APIs to dispel the snag you got stuck.
You can use the code below, if you decide to use async/await:
async function getData() {
const response = await fetch('http://34.198.81.140/attendance.json')
const myData = await response.json()
let startDate = 'Feb 1, 2020'
let endDate = 'Feb 29, 2020'
let result = myData.filter(data => {
return (
// Convert all date values to javascript dates using new Date(value)
// Get the number of milliseconds using getTime()
// Compare the milliseconds values
new Date(data.date).getTime() >= new Date(startDate).getTime() &&
new Date(data.date).getTime() <= new Date(endDate).getTime()
)
})
console.log(result)
}
getData()

Get common data from multiple arrays of object that containing a unique id and nested array using javascript es6

I am trying to find the common data from multiple arrays of object that contains a unique id (mongoose object id) and an array of string.
for example:
array1 = [{
_id: "60f027f98b55eb2df1f36c04",
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: ["8:00 AM", "8:30 AM"]
}]
array2 = [{
_id: "60f027f98b55eb2df1f36c05",
date: "2021-07-15T12:18:12.223Z",
time: "60",
hours: ["7:30 AM", "8:30 AM", "9:30AM"]
}]
array3 = [{
_id: "60f027f98b55eb2df1f36c06",
date: "2021-07-16T12:12:12.223Z",
time: "30",
hours: ["7:00 AM", "8:30 AM"]
}]
The output should have maximum common values in the arrays for maximum common dates and that date should have maximum common hour.
So the sample output should look something like this.
common_data = {
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: "8:30AM"
}
I looked up at other answers and tried something like this:
merged all the arrays and
let result = merged_slots_array.shift().filter(function(v) {
return merged_slots_array.every(function(a) {
const matchDate = a.date === v.date;
const getMatchTime = a.hours.shift().filter(function(x) {
return v.hours.every(function(t) {
return x.indexOf(t) !== -1;
})
});
return matchDate && getMatchTime
});
});
but getting error merged_slots_array.shift(...).filter is not a function
After concatenating the arrays, finding the max common hour can be done through a filter that only keeps duplicates, then gets sorted. Once we have that, we can query each array to make sure it contains the max hour, then extract the max date and time. My output was slightly different than yours because i filtered for the max time, hour and date
array1 = [{
_id: "60f027f98b55eb2df1f36c04",
date: "2021-07-15T12:18:12.223Z",
time: "30",
hours: ["8:00 AM", "8:30 AM"]
}]
array2 = [{
_id: "60f027f98b55eb2df1f36c05",
date: "2021-07-15T12:18:12.223Z",
time: "60",
hours: ["7:30 AM", "8:30 AM", "9:30AM"]
}]
array3 = [{
_id: "60f027f98b55eb2df1f36c06",
date: "2021-07-16T12:12:12.223Z",
time: "30",
hours: ["7:00 AM", "8:30 AM"]
}]
const getCommon = (arrays) => {
let group = [].concat.apply([], [...arrays])
let hour = group.map(e=>e.hours).flat().filter((e,i,a) => a.indexOf(e) !== i).sort((a,b) => a.localeCompare(b))[0]
let common = group.filter(e=>e.hours.includes(hour))
let time = Math.max(...common.map(e => +e.time))
let date = common.map(e => e.date).sort((a,b) => new Date(b) - new Date(a))[0];
return {date: date, time: time, hours: [hour]}
}
let arg = []
arg.push(array1)
arg.push(array2)
arg.push(array3)
console.log(getCommon(arg))
TS Playground

How can I add an element in object at certain position?

I have this object:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
and i want to add an element and have an output like this:
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"land": "111", // THIS <<<<------------
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
i tried using splice but not works...
ages.splice(ages[0]['getasafieldDetail']['asaentrySet'][0]['offerSet'],0,'"land": "111"');
ages.join();
There is the handy syntax of Destructuring assignments which helps with cutting and reassembling objects.
Edit
#FireFuro99 did point to the ES6/ES2015 spec which explicitly states how to preserve/handle an object's key-order at the object's creation time.
Thus one can say ...
Every JS engine which does support Destructuring assignment has to respect too any object's key order from/at this object's creation time.
const ages = [{
getasafieldDetail: {
id: "xxx",
asaentrySet: [{
result: "ON",
buy: {
username: "Dis",
},
offerSet: [{
createdStr: "2001-08-09 at 11:52 pm",
value: 5.0,
}],
}],
},
}];
const { result, buy, ...rest } = ages[0].getasafieldDetail.asaentrySet[0];
ages[0].getasafieldDetail.asaentrySet[0] = {
result,
buy,
land: "111",
...rest,
};
console.log({ ages });
.as-console-wrapper { min-height: 100%!important; top: 0; }
Splice only works on Arrays.
To make this work, convert your Object to an Array using Object.entries(), then use splice, and then convert it back to an object using Object.fromEntries().
const entrySet = Object.entries(ages[0]['getasafieldDetail']['asaentrySet'][0]);
entrySet.splice(2,0, ["land", "111"]);
ages[0]['getasafieldDetail']['asaentrySet'][0] = Object.fromEntries(entrySet);
This will insert the key-value pair at the the specified position.
The advantage this has over the destructuring assignment is, that you can specify the index, whereas destructuring is pretty hardcoded.
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111' will create the key land in the first object in asaentrySet and assign the value 111. Key order is not guaranteed
var ages = [{
"getasafieldDetail": {
"id": "xxx",
"asaentrySet": [{
"result": "ON",
"buy": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "2001-08-09 at 11:52 pm",
"value": 5.0
}]
}]
}
}];
ages[0]["getasafieldDetail"]["asaentrySet"][0].land = '111'
console.log(ages)
When it is an array of objects you could simple, add, passing the position that you want by editing the array like the example below:
let land = {land: 1111}
let ages = [{'a':11},'2', 'wd']
let new =[]
new.push(ages[1])
new.push(land)
ages[1] = new
console.log(ages)
output:
(3) [{…}, Array(2), "wd"]
You get what you want from the array, edit it, and put back in the same position, may it can help.

Categories