I have a data structure like this :
var records = [
{
firstName: "Akira",
id: "0543236543",
},
{
firstName: "Harry",
id: "0994372684",
},
{
firstName: "Sherlock",
id: "0487345643",
},
{
firstName: "Kristian",
id: "04873452342",
},
];
I want to create a function that would add the date property (adjusted for hours) to each of object in the array depending on the length of the array.
Here's my code so far
function updateObject(obj) {
let timeNow = new Date();
let addHours = (h) => timeNow.setHours(timeNow.getHours() + h);
const ids = obj.map((record) => record.id);
const lastNames = obj.map((record) => record.id);
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index)))
);
return obj;
}
This returns:
[
{
firstName: 'Akira',
id: '0543236543',
time: 2021-05-18T12:25:59.366Z
},
{
firstName: 'Harry',
id: '0994372684',
time: 2021-05-18T13:25:59.366Z
},
{
firstName: 'Sherlock',
id: '0487345643',
time: 2021-05-18T15:25:59.366Z
},
{
firstName: 'Kristian',
id: '04873452342',
time: 2021-05-18T18:25:59.366Z
}
]
First issue: I want to update the time by adding 0,1,2,3 hours to the current time.
Currently it:
adds 0 to time and sets is a current time
adds 1 to updated time and set it a as a current time and so on.
Second:
I want to modify the function so it takes an add additional argument, "time increment" that if set to x will update the time property for first x records for 0 hours and the next x records for 1 hour.
Hope that makes sense :)
First issue can be solved by changing addHours to be a pure function that does not mutate timeNow:
const timeNow = Date.now();
const addHours = (h) => new Date(timeNow + h * 60 * 60 * 1000);
Second issue can be solved by looking at the index in the map:
const time = obj.map(
(record, index) => (record["time"] = new Date(addHours(index > increment ? 1 : 0))));
And in general, I would advise against mutating objects/arrays. Pure functions are usually easier to reason about and offer fewer surprises.
I would write the updateObject function so it does not mutate the original, but returns a new array with new objects.
Thanks! What if the increment parameter defines how many first x records should have the time property increased by 1h
For example my contacts array length is 4.
function updateObject(records, 1) {
\\code here
}
The first object would have the time property increased by 0h.
The second object would have the time property increased by 1h.
The third object would have the time property increased by 2h.
The fourth object would have the time property increased by 3h.
function updateObject(records, 3) {
\\code here
}
The first 3 objects would have the time property increased by 0h.
The fourth object would have the time property increased by 1h.
Do I need to slice the array into sub arrays first?
Related
I have an array of events of type.
struct Event { var id: UUID, var title: String, var date: Date }
this array is inside another object with an occurrence title
struct Category { var occurs: String, var events: [Event] }
occurs defines if the event.date is before or after Now(), so that i can make Section Headers in a table to show Past and Upcoming sections.
I am only persisting Event(need id for Notification changes).
I am able to save and load data into an array of Category but how do I add a new event and get it into the correct "occurs" array.
Data Example (Event struc has init that assigns the UUID to id. )
[
Category(occurs: "passed", events: [
Event(title: "Yesterday", date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!)
]),
Category(occurs: "upcoming", events: [
Event(title: "Tomorrow", date: Calendar.current.date(byAdding: .day, value: 1, to: Date())!),
Event(title: "Future", date: Calendar.current.date(byAdding: .day, value: 5, to: Date())!)
])
]
Category array is then consumed by a List/ForEach to spit out the Section and Body.
Thanks
First you need a way to figure out if the event has passed or is upcoming. You could add an extension to your Event struct to compute this:
extension Event {
var occurs: String {
let diff = date.timeIntervalSince1970 - Date().timeIntervalSince1970
return diff >= 0 ? "upcoming" : "passed"
}
}
Next you need to find the index of the category that matches the event's occurs value in your data array. You can do this by using the firstIndex method:
let newEvent = Event(
title: "2 hours from now",
date: Calendar.current.date(byAdding: .hour, value: 2, to: Date())!)
let newEventOccurs = newEvent.occurs
if let index = data.firstIndex(where: { $0.occurs == newEventOccurs }) {
data[index].events.append(newEvent)
}
Notice we use an if-let binding because it's possible you don't have a category in your array for the event. In this case, you will want to add the category to your array with the new event.
I would like to explain my problem of the day.
I have a array which looks like this
[{status: "closed",createdAt: "2022-01-13T15:28:25.239Z"},{status: "closed",createdAt: "2022-01-10T15:28:25.239Z"},{status: "open",createdAt: "2021-11-25T15:28:25.239Z"}]
I filter to retrieve only the data with the status "closed"
const countData = data?.filter(
(item) => item.status === "closed"
);
const count = countData?.length;
this works well, it correctly returns the number to me.
I would like to add a new filter with Luxon.
I would like to take the date of today with luxon, and, as a result, display the objects that correspond to this date
const dateNow = DateTime.now().toISO();
console.log(dateNow)
2022-01-13T16:23:44.873+01:00
How can I fix this issue?
If you want to check if a given Luxon DateTime object represent the same day of today, you can use hasSame passing date as second parameter
Return whether this DateTime is in the same unit of time as another DateTime. Higher-order units must also be identical for this function to return true. Note that time zones are ignored in this comparison, which compares the local calendar time. Use DateTime#setZone to convert one of the dates if needed.
In your case, you can have something like the following code:
const DateTime = luxon.DateTime;
const input = [{
status: "closed",
createdAt: "2022-01-13T15:28:25.239Z"
}, {
status: "closed",
createdAt: "2022-01-10T15:28:25.239Z"
}, {
status: "open",
createdAt: "2021-11-25T15:28:25.239Z"
}, {
status: "closed",
createdAt: new Date().toISOString()
}];
const todayItems = input.filter(item => {
return DateTime.fromISO(item.createdAt).hasSame(DateTime.now(), 'day') && item.status == "closed";
});
console.log(todayItems)
<script src="https://cdn.jsdelivr.net/npm/luxon#2.3.0/build/global/luxon.js"></script>
Luxon has a function that let's you get a date at certain point of a parameter that's called startOf. So you can do something like:
const todayDate = DateTime.now().startOf("day");
So your todayDate variable will be your current date, but at 00:00:00 time.
And you can make the transformation of the elements date during your filter function to compare them to todayDate like this:
//Please consider that the example for today was at 2022-01-13
const array = [
{
name: "this is for today",
date: "2022-01-13T15:28:25.239Z"
},
{
name: "this was for yesterday",
date: "2022-01-12T15:28:25.239Z"
}];
const todayDate = DateTime.now().startOf("day");
const todayElements = array.filter((element) => {
return DateTime.fromISO(element.date).startOf("day").equals(todayDate);
});
I have an array of objects as my initial state like
const [product,setProduct]=useState([
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
])
Here I am also adding more items and at the same time, I Want to calculate the total amount based on quantity*price of each item from the objects. Right now I am proceeding with map() function like this code below and I am getting the exact result
const countTotal=(items)=>
{
var total=0;
product.map(item=>total+=item.quantity*item.price)
setTotal(total)
}
Now My question is if it is a good process or there is an alternative way that is better and standard than this process.
As a general rule, if you have array and want to single value based on all values, you need Array.proptotype.reduce()
const products = [
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
];
const countTotal = (items) => items.reduce((acc, curr) => acc + curr.quantity * curr.price, 0);
console.log(countTotal(products))
You are using .map method incorrectly, you should use reduce method instead, like this
const total = product.reduce((prev, cur) => {
return prev + cur.quantity * cur.price;
}, 0);
I am having difficulty calculating the total votes from the array of choices . I have a json like below
{
id:1,
pollName: 'aaaaa',
pollChoices:[
id: 2,
choice : 'dddd',
votes: [
{
}
]
]
}
I am trying to count the total number votes casted from the jon above within my memoized selectors
My code is like below
const pollChoices: Array<PollChoice> = poll.get("PollChoices").toJS();
const pollStatistic = pollChoices
.reduce((prev: any, curr: any) => {
console.log("The pollStatistic is ", prev);
return { curr, totalVotesCasted: (prev.Votes ?
(prev.Votes.length + curr.Votes.length) :
0 + curr.Votes.length )}
}, {});
console.log("The pollStatistic is ", pollStatistic);
The console within pollStatistic seems to show my totalVotesCasted, however, when i print pollStatistic, its always undefined, i want to be able to get the pollStatistic.totalCount in my state. Pls any help is appreciated.
This is not how reduce works.
You pass the reduce function a reducer callback of this signature: function reducer(accumulator, currentValue, currentIndex) { ... }
The callback should return a the value of the accumulator it wants to be passed to the next iteration.
In your case when you access prev.Votes you should be accessing prev.totalVotesCasted which is the value you set on the accumulator.
In Redux, what's the best practice to update all items in an array with items from another array only with the fields that are common to the 2 arrays.
So for example :
billArrayInStore = [{id, amount, dueDate, summary}, ...]
newBillArray = [{id, amount, dueDate}, ...]
Update each bill (amount, dueDate) but keep the 'summary' field untouched.
Thank you :)
You can use Array.prototype.map
newBillArray = billArrayInStore.map(bill => ({
...bill,
amount: 0, // new amount
dueDate: '', // new dueDate
}))
For each bill object in billArrayInStore, you want to see if there is a corresponding bill object in newBillArray by comparing IDs. If you find a matching bill object, you then merge the two bills together into a new object. These new bill objects are stored in a new array to avoid mutating the original.
Since this solution involves transforming existing bill objects and storing them in a new array, it's a perfect use case for Array.prototype.map.
const updatedBills = billArrayInStore.map(bill => {
// For each existing bill, check to see if there is a corresponding
// new bill by comparing bill IDs.
const newBill = newBillArray.find(newBill => newBill.id === bill.id);
// If there is a new bill, merge the bills together using spread syntax.
if (newBill) {
// Order matters here, you want to spread the new bill last so it
// can override any properties in the current bill. If the current
// bill has properties that don't exist in the new bill, they won't
// be changed.
return { ...bill, ...newBill };
}
// If there isn't a corresponding new bill, the current bill should be
// returned unmodified.
return bill;
});
Here's a snippet with a working example.
const billArrayInStore = [
{ id: 1, amount: 1000, summary: 'Rent' },
{ id: 2, amount: 50, summary: 'Internet' },
{ id: 3, amount: 110, summary: 'Electric' }
];
const newBillArray = [
{ id: 2, amount: 40 },
{ id: 3, amount: 125 }
];
const updatedBills = billArrayInStore.map(bill => {
const newBill = newBillArray.find(newBill => newBill.id === bill.id);
if (newBill) {
return { ...bill, ...newBill };
}
return bill;
});
console.log(updatedBills);