Home > database >  Iterate through List and add to class property retrospectively
Iterate through List and add to class property retrospectively

Time:12-08

I have a schedule which I want to send notifications on. I want to evenly distribute a list throughout a model in order to ensure we have the best reach.

I want to loop through a list of items which it fetched from the database and add them to a time slot on a class which has been specified.

Once it reaches the end of the specified time frame, it'll loop back to the start and keep doing this until all of the users have been allocated a time slot.

I have created the following model for the time slots:

public class Slots 
{
    public List<string> NineAM { get; set; } = default!;

    public List<string> TenAM { get; set; } = default!;

    public List<string> OnePM { get; set; } = default!;

    public List<string> TwoPM { get; set; } = default!;
}

The reason it stores strings is for the email whom the notification is going to be dispatched to. Basically I can check if they have it any items and then dispatch accordingly.

I am unsure how to approach the for loop in order to evenly distribute them out but the current code I have is:

var users = _context.Users.ToListAsync();

users.ForEach(user => 
{
   // Add first user to 9AM
   // Add seconds user to 10AM
  // Add third user to 1PM
   // Add fourth user to 2PM
   // Add fifth user to 9AM
});

Resolution:

Based on the accepted answer I did the following.

  1. Reverted from using a class and properties and arranged my date / times in an array.
private DateTime[] GetTimeSlots()
{
  return new DateTime[]
  {
    DateTime.Now.Date.Add(new TimeSpan(9, 0, 0)),
    DateTime.Now.Date.Add(new TimeSpan(10, 0, 0)),
    DateTime.Now.Date.Add(new TimeSpan(13, 0, 0)),
    DateTime.Now.Date.Add(new TimeSpan(14, 0, 0))
  }
}
  1. Updated the loop.
var slots = GetTimeSlots();

foreach (var user in users)
{
  var userIndex = users.indexOf(user);
  var targetSlotIndex = userIndex % slots.Length;
  
  var targetTime = slots[targetSlotIndex];
  // This resulted in the time iterating accordingly.
}

This allowed for time slots to be much more dynamic when adding / removing new ones.

CodePudding user response:

You have 4 slots, so divide your users into four groups, and add them to the appropriate slot. You can use the % operator to see which slot they go into.

foreach(var user in users)
{
    switch (users.IndexOf(user) % 4)
    {
        case 0:
           //add to NineAM
           break;
        case 1:
           //add to TenAM
           break;
        case 2:
           //add to OnePM
           break;
        case 3:
           //add to TwoPM
           break;
    }
}

CodePudding user response:

This is a Round Robin distribution, and I just recently had to write something similar. I also used the % operator for my solution.

The Resolution you posted is unnecessarily inefficient though. You don't need to call users.indexOf(user), because there is a cost to search the list for the user and that cost can be eliminated. It is far more efficient to do this by just tracking the iteration of the loop that you are in.

get rid of this

var userIndex = users.indexOf(user);

and use one of these solutions

var slots = GetTimeSlots();
for(int i=0; i < users.Count; i  )
{
    var userIndex = i % slots.Count;
    var targetTime = slots[userIndex];
}

OR 

int iterator = 0;
var slots = GetTimeSlots();
foreach (var user in users)
{
    var userIndex = iterator % slots.Count;
    var targetTime = slots[userIndex];
    iterator  ;
}
  • Related