Loop through an array and push it into array of object javascript - javascript

So i try to loop an Array and push it into object within this code:
const past7Days = [...Array(7).keys()].map(index => {
var date = new Date();
const local = new Date();
local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
local.setDate(date.getDate() - index);
return local.toJSON().slice(0, 10);
});
let data={};
let arr=[]
for (var i = 0; i < past7Days.length; i++) {
console.log(past7Days[i]);
return arr.push(data["key"] = past7Days[i])
}
what i expected is :
[{key:"date"},{key:"date2"}]
can somebody tellme where did i do wrong here

In your attempt there is only one such object created (data) and the assignments to data[key] just keep overwriting the same object's property. Moreover, that push will not push an object, but the string that is assigned.
You can create each object immediately in your first iteration, with a { key: string-value } object literal and returning that.
Unrelated, but you should not use getTimezoneOffset like that. In boundary cases (like when daylight saving switches on the same day) it can have undesired results. Instead consider that you can convert a date to a string with respect of the current locale's timezone. For instance, the Swedisch locale also uses "YYYY-MM-DD" format (like toJSON), and when used with toLocaleDateString it will use the locale's date:
const past7Days = Array.from({length: 7}, (_, index) => {
const local = new Date();
local.setDate(local.getDate() - index);
return { key: local.toLocaleDateString('en-SE') };
});
console.log(past7Days);

Assuming you want exactly one array where the elements are like {"key": <string representation of a date> }, you can try this:
const past7Days = [...Array(7).keys()].map(index => {
var date = new Date();
const local = new Date();
local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
local.setDate(date.getDate() - index);
return local.toJSON().slice(0, 10);
});
let arr=[]
for (var i = 0; i < past7Days.length; i++) {
// console.log(past7Days[i]);
arr.push( {key: past7Days[i] } )
}
console.log(arr);

Related

Separate array after each second comma

I got an array from a CMS that is poorly formatted which I want to reformat to an array of objects.
let daysOffArray = ["2022-08-22, 08:00 - 14:00","2022-08-23, 08:00 - 13:00"];
Expected result after separating the array:
let daysOff = [{
date: "2022-08-22",
time: 08:00 - 14:00
},
{
date: "2022-08-23",
time: 08:00 - 13:00
}];
How can I separate the array daysOffArray for each second comma and then separate the two new arrays after each comma?
You can use array destructuring and the object literal property value shorthand for a more concise solution and better readability.
daysOffArray.map(item => {
const [date, time] = item.split(', ');
return { date, time };
});
// Initial object
var daysOffArray = [
'2022-08-22, 08:00 - 14:00',
'2022-08-23, 08:00 - 13:00',
];
// An empty array for the formatted object
var daysOffFormatted = [];
// Splitting and formatting the array
daysOffArray.forEach((daysOff) => {
var date = daysOff.split(',')[0].trim();
var time = daysOff.split(',')[1].trim();
// Adding formatted object to the array
daysOffFormatted.push({ date, time });
});
console.log(daysOffFormatted);
Use String#split and Array#map:
let daysOff = daysOffArray.map(item => {
const data = item.split(", ");
return { date: data[0], time: data[1] };
});
let daysOffArray = ["2022-08-22, 08:00 - 14:00","2022-08-23, 08:00 - 13:00"];
let daysOff = [];
daysOffArray.forEach((item) => {
daysOff.push({ date: item.split(",")[0], time: item.split(",")[1] });
});
console.log(daysOff);
let daysOff = daysOffArray.map((datetime)=>{
const [date, time] = datetime.split(',');
return {date, time: time.trim()};
});

How to find index of object in array with latest date

I have an array of objects in an array. Each object has a date field. Here is a method I wrote to retrieve the index of the object with the newest date, works fine:
GetIndexOfLatestDate()
{
var indexOfLatestDate:number = 0;
var maxDate:number = new Date(this.objArray[0].date).getTime();
for(var nIndex:number = 1; nIndex < this.m_objArray.length; nIndex++)
{
if(new Date(this.objArray[nIndex].date).getTime() > maxDate)
{
maxDate = new Date(this.objArray[nIndex].date).getTime();
indexOFLatestDate = nIndex;
}
}
return indexOfLatestDate;
}
How can this be written (much) more succinctly?
Thanks for any help.
I would suggest using the reduce function that javascript provides. This solution also doesn't loop through the array multiple times, and it calls new Date().getTime() once per date.
GetIndexOfLatestDate()
{
if (this.objectArr === null || this.objectArr.length === 0) {
return null;
}
return this.objectArr.reduce((accum, value, index) => {
const newDate = new Date(value.date).getTime();
return newDate > accum.maxDate ? {index, maxDate: newDate} : accum;
}, {index: 0, maxDate: new Date(this.objectArr[0].date).getTime()}).index;
}
if this looks too confusing, here is an expanded version that's easier to follow if you are new to the reduce function.
GetIndexOfLatestDate()
{
// check if object arr is empty
if (this.objectArr === null || this.objectArr.length === 0) {
return null;
}
// set default accumulator for first passthrough
const defaultAccum = {
index: 0,
maxDate: new Date(this.objectArr[0].date).getTime()
}
const maxValueWithIndex = this.objectArr.reduce((accum, value, index) => {
// set formatted date to prevent multiple Date() calls
const newDate = new Date(value.date).getTime();
// if the new date is larger than the current largest date, set
// the accumulator to the new largest date and its index
if (newDate > accum.maxDate)
accum = {
index: index,
maxDate: newDate
};
}
// return the current accumulator, i.e. the current largest date
return accum;
}, defaultAccum);
// return the index of the latest date
return maxValueWithIndex.index;
}
You can do this using built-in function like this
const array1 = [{date: '2/5/2021'}, {date: '3/11/2019'}, {date: '12/9/2022'}];
const dateArray = array1.map(({date}) => {return new Date(date)})
const maxDate = Math.max(...dateArray);
const indexMaxElem = dateArray.findIndex(dateObj => dateObj.getTime() === maxDate)
console.log(indexMaxElem)
It is less efficient though, since it needs to do multiple pass through the array
let dateArr = [];
objArray.forEach(item => {
// extract the dates from the source array to form new array
dateArr.push(objArray.date.getTime();
});
// find the maximum date in this array, which will have the same index
indexOfLatest = dateArr.findIndex(Math.max(...dateArr));
GetIndexOfLatestDate(objArray){
let max = objArray.reduce(function (a, b){ return new Date(a.date) > new
Date(b.date) ? a : b; });
return objArray.indexOf(max);
}
You can do it with a reduce, something like:
index = this.objArray.reduce((accum, value, index) => {
if(!accum){
accum = {
index,
maxDate: value.date
};
} else {
if(accum.maxDate.getTime() > value.date.getTime()){
accum = {
index,
maxDate: value.date
};
}
}
return accum;
}
}, null).index;

Getting loop when checking Array Object for match and pushing object when none found

Here is my code:
function createMatchList(data) {
var matchArray = [];
for (var i = 0; i < initialData.length; i++) {
var listData = cleanData(initialData[i][data]);
if (matchArray.length) {
for (var a = 0; a < matchArray.length; a++) {
if (matchArray[a][data] == listData) {
matchArray[a].Count = matchArray[a].Count + 1;
} else {
// THIS CAUSES LOOP
matchArray.push({ [data]: listData, "Count": 1 });
}
}
} else {
matchArray.push({ [data]: listData, "Count": 1 });
}
}
}
Essentially, this appears to work outside of when a matching object isn't found, I have an else to push that object to the array and it causes a loop.
I'm not sure why this would happen and I'm totally lost..
I have an initial if/else to see if the array is empty, if it is empty, push the initial object into the array, past this point if the array isn't empty, I check the array using a for loop and the if statement works, but my else statement causes the loop. If I were to take that matchArray.push({ [data]: listData, "Count": 1 }); out of the else statement and just console.log something, it would successfully log for each additional iteration in the first for loop for the initialData.
And just to give an idea of what the array looks like with an object in it:
[
{
Date: "27 June 1911",
Count: 1
}
]
My goal is to search the Array for matching Dates and if there is a match, don't push to the Array but instead update the Count. The reason for this is I have a huge raw JSON file with duplicates and I'm trying to create a new data source removing duplicates but counting the occurrences.
Thanks
Use Set and Array.filter():
[...new Set(dates)].map(date => ({
date,
count: dates.filter(currDate => date === currDate).length
}));
Note: By convention object keys should be lowercased, date and not Date.
Or if you feel brave:
const counts = {};
dates.forEach(date => (counts[date] = (counts[date] || 0) + 1));
const dates = [
'27 June 1911',
'27 June 1952',
'27 March 1911',
'27 June 1952',
'24 June 1911',
'27 June 1952'
];
const datesCount = [...new Set(dates)].map(date => ({
date,
count: dates.filter(currDate => date === currDate).length
}));
console.log('datesCount', datesCount);
const counts = {};
dates.forEach(date => (counts[date] = (counts[date] || 0) + 1));
const dateCount2 = Object.entries(counts).map(([date, count]) => ({
date,
count
}));
console.log('dateCount2', dateCount2);
// Make unique array of dates.
const datesSet = [...new Set(dates)];
// Count by filtering the array and getting it's length.
const datesCount = datesSet.map(date => ({
date,
count: dates.filter(currDate => date === currDate).length
}));
How important is performance and are you using >= 2015? If so, you could just map instead and reduce some code complexity like this answer:
const counts = new Map([...new Set(a)].map(
x => [x, a.filter(y => y === x).length]
));
Then to get the count you would just call:
counts.get(x)
In the case where you need to store it in an object that looks exactly as you've outlined above, I would do something like:
let unique = Set(dates);
var matchArray = [];
unique.forEach(function (date) {
matchArray.push({
"Date": date,
"Count": dates.filter(x => x === date).length
});
});

Javascript: Filter Array with duplicate Dates

I´m using Angular2 and I have an array with Date-Objects (~1000).
Most of the Date-Objects have got the exactly same dates (for example 2016_11_02; Dates have no hours & minutes).
Normally there should be about ~10-20 different Dates in the Array.
Now i want to filter this array and delete the duplicate Dates.
So in the end there should be about ~10-20 Date-Objects in the array.
Here´s the code i tried:
let uniqueArray = duplicatesArray.filter(function(elem, pos) {
return channelEPGDates.indexOf(elem) == pos;
});
console.log('unique: ' + uniqueArray.length);
I know this is not correct, cause the unique-Array has the same length as the old array. But how can i compare the Dates itself in the filter-function?
Thanks so much!
I would map the dates to epoch time using the getTime method, and then map them back to Date objects.
let uniqueArray = duplicatesArray
.map(function (date) { return date.getTime() })
.filter(function (date, i, array) {
return array.indexOf(date) === i;
})
.map(function (time) { return new Date(time); });
You could use Set and the spread syntax ... for it.
unique = src => [...new Set(src)];
var unique = src => [...new Set(src)];
array = ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Nancy", "Carl"];
console.log(unique(array));
To get objects with unique dates, you could filter the data by using a closure over a Set and a callback for getting the part which has to be unique.
var unique = (src, fn) => src.filter((s => o => !s.has(fn(o)) && s.add(fn(o)))(new Set));
array = [{ date: new Date('2019-11-01')}, { date: new Date('2019-11-01')}, { date: new Date('2019-11-01')}, { date: new Date('2019-11-02')}, { date: new Date('2019-11-01')}, { date: new Date('2019-11-05')}, { date: new Date('2019-11-05')}, { date: new Date('2019-11-04')}, { date: new Date('2019-11-07')}];
console.log(unique(array, ({ date }) => date.toISOString().slice(0, 10)));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do with jQuery like this :
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
Here is a method using the built-in methods on Array.
var arr = ["John", "Jimmy", "John"];
var dArr = []; //Date array
while (dArr.length < 10000) { //Load a lot of pseudo dates
dArr.push(
new Date().getTime() + Math.round(Math.random() * 10)
);
}
function arrayUnique(arr) {
return arr.reduce(function(previousValue, currentValue) {
if (previousValue.some(function(value, index) {
return value === currentValue;
}) === false) {
previousValue.push(currentValue);
}
return previousValue;
}, []);
}
console.log(arrayUnique(arr));
console.log(arrayUnique(dArr).sort());

Update object key value

Been trying to figure this out for the past hour, but can't seem to get it. I am trying to make an array with the dates of the last X days. Here is an example:
var dates = [];
var curr = new Date();
var first = curr.getDate();
dates.push(new Date(curr.getTime()).toISOString().split('T')[0]);
for(var i = 1; i < 6; i++){
var previous = new Date(curr.getTime());
previous.setDate(first - i);
dates.push(previous.toISOString().split('T')[0]);
}
console.log(dates);
The result gives me:
["2014-03-18", "2014-03-17", "2014-03-16", "2014-03-15", "2014-03-14", "2014-03-13"]
How would I put that in this format for my chart?
var chartData = [{day: '2014-03-18',clicks: 8,success: 4},
{day: '2014-03-17',clicks: 41,success: 3},
{day: '2014-03-16',clicks: 20,success: 1},
{day: '2014-03-15',clicks: 46,success: 3},
{day: '2014-03-14',clicks: 34,success: 2}];
I need to be able to add clicks and success as well, but since the varaible name is dynamic I am having a hard time. I tried bracket notations, along with dots and I can't get it to work.
Anyone know how I would achieve this?
Thank you in advance!
Fundamentally, to put an object in your array rather than a string, you create the object:
dates.push({
day: previous.toISOString().split('T')[0],
clicks: 0,
success: 0
});
Then later to update:
++dates[someIndex].success;
or
dates[someIndex].clicks = 27;
You said:
...but since the varaible name is dynamic I am having a hard time
...but didn't say what variable you were talking about. If you mean the name of the property, like click or success, that's okay, you can use bracketed notation and a string:
var obj = {day: previous.toISOString().split('T')[0]};
obj[variableWithNameForClicks] = 0;
obj[variableWithNameForSuccess] = 0;
dates.push(obj);
and
++dates[someIndex][variableWithNameForSuccess];
or
dates[someIndex][variableWithNameForClicks] = 27;
That works because in JavaScript, you can access object properties in two ways: Dotted notation with a literal property name (obj.foo), or bracketed notation with a string property name (obj["foo"]). In the bracketed notation, the string can be the result of any expression, including a variable lookup. So:
var obj = {clicks: 27};
var str = "clicks";
console.log(obj[str]); // 27
See the codepen here.
var dates = [];
var curr = new Date();
var first = curr.getDate();
// Using variable object property names
var dayVar = "day";
var clicksVar = "clicks";
var successVar = "success";
// Increment from 0 instead of 1 so you don't have to repeat yourself
for ( var i = 0; i < 6; i++ ){
var dateObj = {};
var previous = new Date(curr.getTime());
previous.setDate(first - i);
dateObj[dayVar] = previous.toISOString().split('T')[0];
dateObj[clicksVar] = 0;
dateObj[successVar] = 0;
dates.push(dateObj);
}
// Increment clicks
dates[0][clicksVar] += 1;
// Increment success
dates[0][successVar] += 1;
console.log(dates);
If you want to go back and find the object for a certain date, you might use a js library like underscore, or you could do something like this:
// Today's date
var searchDate = new Date(curr.getTime()).toISOString().split('T')[0];
// Search through the array for the matching object
for (var i = 0; i < searchDate.length; i++) {
var obj = dates[i];
if ( obj.day === searchDate ) {
console.log(obj);
break;
}
}

Categories

Resources