How to check the condition the array contains the element in javascript? - javascript

Code:
monthArray = ["jan 2009", ..., "dec 2009"];
The jsonFile contains:
[
{
"month": "Aug 2012",
"no_Of_Commits": 1
},
{
"month": "Jun 2012",
"no_Of_Commits": 1
},
{
"month": "Apr 2012",
"no_Of_Commits": 6
}
]
function populate(jsonFile) {
tempJson = jsonFile;
for (var i = 0; i < monthArray.length; i++)
{
if (monthArray.contains(tempJson[i]["month"])) // condition Not working suggest anything else
{
console.log("yes");
tempJson[i]["no_Of_Commits"] = tempJson[i]["no_Of_Commits"];
}
else
{
console.log("NO");
jsonFile[i]["no_Of_Commits"] = 0;
}
}
}

Replace contains with indexOf
if ( monthArray.indexOf( tempJson[i]["month"] ) !== -1 ) {...
and as you're iterating over one array, and getting values from another array, you better make sure both arrays have the same number of indices etc.

Related

Filter an array of objects with latest date if array contains same date with different timestamp in multiple objects

I have an array of objects and each object has the date. I need to filter the array and get the objects that contains latest date.
[
{
"Id": 25,
"MeasureDate": "2022-08-26T00:01:01.001Z"
},
{
"Id": 26,
"MeasureDate": "2022-08-26T11:10:01.001Z"
},
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 30,
"MeasureDate": "2022-08-27T00:08:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
]
After filtering the array I need the array should look like below
[
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
]
const dateItems = [
{
"Id": 25,
"MeasureDate": "2022-08-26T00:01:01.001Z"
},
{
"Id": 26,
"MeasureDate": "2022-08-26T11:10:01.001Z"
},
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 30,
"MeasureDate": "2022-08-27T00:08:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
];
// As we loop through your dateItems array we need to keep track of the Latest DateTime for each day
// Probably the easiest way is to create a key on a property for each date and then attach the object
// from your array to that key if it is the first for that date or later than an existing one.
const latestDateTimesByDate = {};
dateItems.forEach( di => {
// Use the date part of the date time as a key/ property name on the latestDateTimesByDate object
let dateKey = di.MeasureDate.substring(0, 10);
// If that date key doesnt exist or the current MeasureDate is gretaer than the recorded one
if( !latestDateTimesByDate[dateKey] || di.MeasureDate > latestDateTimesByDate[dateKey].MeasureDate) {
latestDateTimesByDate[dateKey] = di;
}
});
// if you need it as an array then add each of the date properties to an element of an array
const finalArray = [];
Object.keys(latestDateTimesByDate).forEach( key => finalArray.push(latestDateTimesByDate[key]));
Here's a solution for your probleme :
function similarDates(obj){
date_obj = new Date(obj.MeasureDate);
// Getting only the dates with same year, month, day
let sim_dates = popo.filter((objs) => {
date = new Date(objs.MeasureDate)
return date.toDateString() === date_obj.toDateString()
});
// Returning the similare dates
return sim_dates
}
function filterData(array) {
result = []
while(array.length) {
console.log(array)
var sameElement = similarDates(array[0]);
// removing all the treated elements from the array
array = array.filter( ( el ) => !sameElement.includes(el));
result.push(sameElement.sort((a, b) => new Date(b.MeasureDate) - new Date(a.MeasureDate)).shift());
}
return result;
}

How to merge duplicate object parent items in array?

I want to merge objects in array so that objects with the same id (which is a child object) can sum the total_price and total_quantity values.
Here is my data array:
var data = [
{
"_id": {
"month": 5,
"year": 2021
},
"total_price": 145111500,
"total_quantity": 7
},
{
"_id": {
"month": 6,
"year": 2021
},
"total_price": 98386000,
"total_quantity": 5
},
{
"_id": {
"month": 6,
"year": 2021
},
"total_price": 32500000,
"total_quantity": 3
}
]
I want to merge objects that have the duplicate "_id". Here is the output result:
var merge = [
{
"_id": {
"month": 5,
"year": 2021
},
"total_price": 145111500,
"total_quantity": 7
},
{
"_id": {
"month": 6,
"year": 2021
},
"total_price": 130886000,
"total_quantity": 8
}
]
Thanks in advance.
const data = [
{ "_id": { "month": 5, "year": 2021 }, "total_price": 145111500, "total_quantity": 7 },
{ "_id": { "month": 6, "year": 2021 }, "total_price": 98386000, "total_quantity": 5 },
{ "_id": { "month": 6, "year": 2021 }, "total_price": 32500000, "total_quantity": 3 }
];
const res = [...
// iterate over the list
data.reduce((map, item) => {
// construct key from _id
const key = `${item._id.month}-${item._id.year}`;
// get prev map value of key if exists
const prev = map.get(key);
// update map, if prev not found, set value as item, or update it with the added values
map.set(
key,
!prev
? item
: { ...item, total_price: prev.total_price + item.total_price, total_quantity: prev.total_quantity + item.total_quantity }
);
return map;
}, new Map)
// return map values
.values()
];
console.log(res);
var ids = [];
var merge = [];
for (let i = 0; i < data.length; i++) {
obj = data[i];
let dupId = false;
for (let j = 0; j < ids.length; j++) {
if (ids[j]["month"] == obj["_id"]["month"] && ids[j]["year"] == obj["_id"]["year"]) {
merge[j]["total_price"] += obj["total_price"];
merge[j]["total_quantity"] += obj["total_quantity"];
dupId = true;
break;
}
}
if (!dupId) {
ids.push(obj["_id"]);
merge.push(obj);
}
}
The code will:
Declare and initialize merge array to an empty array
Loop through all elements from data array
And inside, check for duplicate of element in merge array
If found, add total quantities and total prices
If not found, add element to merge array

momentjs iterate over dates in a two week period and map the date to existing array

I have an array that has a object with two properties, 'location' and 'needs'. The needs property has an array of objects with a date and count {date: "2021-06-15", count: 10} so an array would look like this:
{
"location": "NYC",
"needs": [
{
"date": "2021-04-06",
"count": 56
},
{
"date": "2021-04-13",
"count": 10
}
]
}
What I need to do is to use Momentjs to use today's date, figure out the two week period starting from today, and then map the needs-count to the date in the moment loop. If there is a date missing (like in the example below), it should put a 0 as the count
A final array would look like...
{
"location": "NYC",
"needs": [
{
"date": "2021-04-06",
"count": 56 // this had a count in the initial object
},
{
"date": "2021-04-07",
"count": 0
},
{
"date": "2021-04-08",
"count": 0
},
{
"date": "2021-04-09",
"count": 0
},
{
"date": "2021-04-10",
"count": 0
},
{
"date": "2021-04-11",
"count": 0
},
{
"date": "2021-04-12",
"count": 0
},
{
"date": "2021-04-13",
"count": 10 // this had a count in the initial object
},
...
...
...
]
}
In terms of a function, the closest I have got is
let startDay = moment().format('YYYY-MM-DD');
let endDay = moment().add(14, 'days').format('YYYY-MM-DD');
let startDate = moment(startDay);
let endDate = moment(endDay);
let datesBetween = [];
let startingMoment = startDate;
while(startingMoment <= endDate) {
for (let count = 0; count < 15; count ++) {
// at this point im trying to take 'week' which has the location property and needs property and trying to merge them together... but failed miserably.
if (week.needs[count].date === startingMoment) {
datesBetween.push([startingMoment.clone(), week.needs[count].count]);// clone to add new object
startingMoment.add(1, 'days');
} else {
datesBetween.push([startingMoment.clone(), 0]);// clone to add new object
}
}
}
Can someone see where I went so wrong?
const week = {
"location": "NYC",
"needs": [
{
"date": "2021-04-06",
"count": 56
},
{
"date": "2021-04-13",
"count": 10
}
]
}
let current = moment();
const allDates = [];
const FORMAT = 'YYYY-MM-DD';
for (let count = 0; count < 14; count++) {
const found = week.needs.find(i => i.date === current.format(FORMAT));
if (found) {
allDates.push(found);
} else {
allDates.push({
date: current.format(FORMAT),
count: 0,
});
}
current.add(1, 'day');
}
week.needs = allDates;
console.log(week);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>
You could do something like this :
let dates = {
"location": "NYC",
"needs": [
{
"date": "2021-04-06",
"count": 56
},
{
"date": "2021-04-13",
"count": 10
}
]
};
let day = moment();
for( let i=0; i< 15; i++){
let date = day.add(1, "days").format("YYYY-MM-DD");
console.log(`Looking if ${date} is in array...`)
if(dates.needs.find(obj => obj.date === date)) continue;
console.log(`Adding ${date}`)
dates.needs.push({ date, count : 0 })
}
dates.needs.sort( (a,b) => a.date > b.date ? 1: -1 );
console.log(dates)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

Transform a list of dictionaries into a dictionary of lists with Javascript

Is there a built-in Javascript function to transform a list of dictionaries:
const L =
[ { "day": "20201210", "count": "100" }
, { "day": "20201211", "count": "120" }
, { "day": "20201212", "count": "90" }
, { "day": "20201213", "count": "150" }
]
into a dictionary of lists like this:
const D =
{ "day" : [ "20201210", "20201211", "20201212", "20201213"]
, "count" : [ "100", "120", "90", "150"]
}
? If not what's the simplest way to do it in JS?
(It is a little-bit similar to matrix "transpose" operation).
Note: here it's a transpose and not a groupby like in Most efficient method to groupby on an array of objects
Assuming all objects have the same keys and your array is not empty, this will work:
let D = {};
Object.keys(L[0]).forEach(k => {
D[k] = L.map(o => o[k]);
});
There are certainly more efficient solutions but this is short and concise and not too bad in terms of efficiency.
Here's a fairly short and efficient method for general values.
L.forEach(o => {
Object.keys(o).forEach(k => {
D[k] ||= [];
D[k].push(o[k]);
});
});
const L = [{
"day": "20201210",
"count": "100"
}, {
"day": "20201211",
"count": "120"
}, {
"day": "20201212",
"count": "90"
}, {
"day": "20201213",
"count": "150"
}]
let D = {};
L.forEach(o => {
Object.keys(o).forEach(k => {
D[k] ||= [];
D[k].push(o[k]);
});
});
console.log(D);
I don't think such a function exists, at least in vanilla JavaScript.
A simple, pure vanilla and clear to understand way of doing it would be like this:
var L = [
{
"day": "20201210",
"count": "100"
},
{
"day": "20201211",
"count": "120"
},
{
"day": "20201212",
"count": "90"
},
{
"day": "20201213",
"count": "150"
}
];
var D = { };
for (var dict in L)
{
for (var key in L[dict])
{
if (D[key] == null) {
D[key] = [ ];
}
D[key].push(L[dict][key]);
}
}
This is definitely not the most concise or most optimized way of doing it, though it will work.
You can just restructure your array of dictionaries as such, and re-map it with Array.prototype.map
E.g. (The following practice requires to iterate the elements with map N * X times where N is the length of L and X is the amount of properties you'd want to have in D, ignore this if you have many properties you'd want to watch.)
But, this is the easiest readable approach that I'd want to introduce to you before the 2nd approach.
const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
const D = {
'day': L.map(elem => elem['day']),
'count': L.map(elem => elem['count']),
};
console.log(D);
Another approach I'd suggest is to use Array.prototype.reduce, this is by far favored in your case as it's easily expandable by adding more properties to the initial array.
const L = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
const D = L.reduce((acc, cv) => {
for (const propertyToGrab in acc) {
if (cv.hasOwnProperty(propertyToGrab)) {
acc[propertyToGrab].push(cv[propertyToGrab]);
}
}
return acc;
}, {
'day': [],
'count': []
});
console.log(D);
const D={day:[], count:[]};
for(const item of L){
D.day.push(item.day);
D.count.push(item.count);
}
const input = [{"day":"20201210","count":"100"},{"day":"20201211","count":"120"},{"day":"20201212","count":"90"},{"day":"20201213","count":"150"}];
// Create a variable that will store the result
let result = {};
// Loop through the input with forEach
input.forEach((element) => {
// Loop through the keys
for(let key in element) {
// Check if a key is not exist in the result
if(!result.hasOwnProperty(key)) {
// Then create an key and assign an empty array to it
result[key] = [];
}
// Push the elemnts to the array.
result[key].push(element[key]);
}
});

Blank data for certain hours - hence missing in my array. Is there a way to fill in the missing hours?

I have some data by the hour and summarise/consolidate the array.
However, there are some hours which are blank in data.Items hence my array would skip the data point completely.
Is there a way where I can through my data/array and fill in the gaps and assign a '0' next to it?
for(i=0; i<dataLength; i++){
var date = new Date(data[i].ctimestamp);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
var date = moment(date).tz("Pacific/Auckland").format("DD/MM/YY HH:mm");
dateArray.push({"date" : date});
}
Here is an example - "11/12/18 05:00" and "11/12/18 06:00" are missing so it's skipped completely.
[{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 04:00",
"count": 6
}]
Ideally, I would like it to show:
[
{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 06:00",
"count": 0
},
{
"date": "11/12/18 05:00",
"count": 0
},
{
"date": "11/12/18 04:00",
"count": 6
}]
I think this simplifies the logic and produces the result you want:
const data = [
{
"date": "11/12/18 08:00",
"count": 5
},
{
"date": "11/12/18 07:00",
"count": 4
},
{
"date": "11/12/18 04:00",
"count": 6
}
];
let min = Number.MAX_VALUE;
let max = 0;
const dates = data.reduce((memo, {date, count}) => {
const time = new Date(date).getTime();
min = Math.min(min, time);
max = Math.max(max, time);
memo[time] = count;
return memo;
}, {});
const ONE_HOUR = 60 * 60 * 1000;
const dataOutput = [];
for (let i = min;i <= max;i += ONE_HOUR) {
dataOutput.push({
date: new Date(i).toLocaleString(),
count: dates[i] || 0
});
}
console.log(dataOutput)
I'll assume the array you posted as sample data, is called dataItems. Also, I'll use moment to handle time, but you can convert it to vanilla JS if you want.
So, what I would do is go through dataItems, and check if prev value is 1 hour prev to this value, if its not, add a new input.
dataItems.reduce((acc, val) => {
if(!acc) {
return [moment(val)];
}
let momentVal = moment(val)
if (momentVal.diff(acc[acc.length - 1], 'hours') !== 1){
acc.push(momentVal)
return acc;
} else {
while(momentVal.diff(acc[acc.length - 1], 'hours') !== 1){
acc.push(moment(acc[acc.length - 1]).add(1, 'hours')) //clone and add 1 hour
}
}
}])
I didn't take in consideration your object isn't just date, but that should be simple to adapt. The general logic is: go through your array, if the previous one is 1 hour less than right now, keep it going. Else, add a new input until the actual one is 1 hour after the last one on the array

Categories