• Welcome to TechPowerUp Forums, Guest! Please check out our forum guidelines for info related to our community.

c# subtract elements of a list

Joined
May 27, 2008
Messages
3,628 (0.62/day)
System Name Ultra 64
Processor NEC VR4300 (MIPS R4300i)
Motherboard proprietary design
Cooling Fanless aircooled
Memory 4.5MB 250 MHz RDRAM
Video Card(s) 62.5 MHz Reality Coprocessor
Storage 32 - 512 Mbit ROM Cartridge
Display(s) 720x576
Case Clear Blue Funtastic
Audio Device(s) 16-bit CD quality
Power Supply proprietary design
Mouse N64 mouse for use with N64DD
Keyboard N64 keyboard for use with N64DD
Hi all

I have two lists of DateTime. One represents the start time of a task, the second the finish time. I need to subtract the contents of one from the other to end up with a list representing the duration of each task. Im aware that subtracting two DateTime's returns a TimeSpan and that is great for what I need.

Im currently performing it within a series of loops as im still stuck im my programming ways for c# in microcontrollers doing DSP but now im using asp.net and wondering if theres any extra functionality of this framework that can perform the task in a more elegant and readable way.

Theres no need to worry about aligning the data in the list as they are already aligned, so the first elements of each list match, second, third etc.

Many thanks all

Stephen
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
I would put the start and finish times in a custom class then add an instance of the class to a List<class>. That way you only have one list and that one list contains everything relevant. If you want to go a step further, I would add an accessor called Duration that returns Finish - Start. Put it all together, you could do something like list[9].Duration to get how long task 9 took. Ideally, this custom class would contain everything relevant to the job (even the job itself) so this all happens in isolated code.

To remove elements from a list, use .Remove(index) or .Remove(copy of instance). If it is in a for loop, make sure to run the loop in reverse (i-1) otherwise it will freak out.

If this isn't homework and the code is something that can be made public, I could take a look and/or optimize it for you so you can see a working example of what I'm talking about.
 
Last edited:
Joined
Feb 8, 2012
Messages
3,013 (0.68/day)
Location
Zagreb, Croatia
System Name Windows 10 64-bit Core i7 6700
Processor Intel Core i7 6700
Motherboard Asus Z170M-PLUS
Cooling Corsair AIO
Memory 2 x 8 GB Kingston DDR4 2666
Video Card(s) Gigabyte NVIDIA GeForce GTX 1060 6GB
Storage Western Digital Caviar Blue 1 TB, Seagate Baracuda 1 TB
Display(s) Dell P2414H
Case Corsair Carbide Air 540
Audio Device(s) Realtek HD Audio
Power Supply Corsair TX v2 650W
Mouse Steelseries Sensei
Keyboard CM Storm Quickfire Pro, Cherry MX Reds
Software MS Windows 10 Pro 64-bit
I would put the start and finish times in a custom class then add an instance of the class to a List<class>. That way you only have one list and that one list contains everything relevant. If you want to go a step further, I would add an accessor called Duration that returns Finish - Start. Put it all together, you could do something like list[9].Duration to get how long task 9 took. Ideally, this custom class would contain everything relevant to the job (even the job itself) so this all happens in isolated code.

This.
Create EventInfo class with DateTime EventStart, DateTime EventEnd, and a TimeSpan property Duration (with only getter) that gets EventEnd-EventStart.
Then you keep the list of EventInfo instances.
 
Joined
May 27, 2008
Messages
3,628 (0.62/day)
System Name Ultra 64
Processor NEC VR4300 (MIPS R4300i)
Motherboard proprietary design
Cooling Fanless aircooled
Memory 4.5MB 250 MHz RDRAM
Video Card(s) 62.5 MHz Reality Coprocessor
Storage 32 - 512 Mbit ROM Cartridge
Display(s) 720x576
Case Clear Blue Funtastic
Audio Device(s) 16-bit CD quality
Power Supply proprietary design
Mouse N64 mouse for use with N64DD
Keyboard N64 keyboard for use with N64DD
Thanks I will look into your methods.

Nope this isn't homework but it is for work. recently got my first job as a web developer and its technology I've never worked with before (any .net technology) so its a little tough to adapt my current programming techniques around this new, to me, framework. So in a nut shell I wan't to do it off my own back and even if I wanted to give you code I couldn't but the offer is appreciated. plus you've given me the idea of how to do it which should enough to work the rest out myself so thanks all.
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
What I suggested is basically making the code object-oriented instead of procedural. I'll give a basic example using pseudo-variables:
Code:
using System;

public class Task
{
  private DateTime _Start = new DateTime();
  public DateTime Start
  {
    get { return _Start; }
    set { _Start = value; }
  }

  private DateTime _Stop = new DateTime();
  public DateTime Stop
  {
    get { return _Stop; }
    set { _Stop = value; }
  }

  public TimeSpan Duration
  {
    get { return _Stop - _Start; }
  }

  public Task() { }
  public Task(DateTime start, DateTime stop)
  {
    _Start = start;
    _Stop = stop;
  }
}
I didn't compile the above code but it should work.

Duration could be made into a function but I decided to make it a read-only property because you may have never seen one of those before. They're useful for menial tasks like a quick subtraction.

Additionally, I don't know if you're using strongly-typed lists but I'd recommend using them. It eliminates all the silly type-casting. They are in System.Collections.Generic and called like List<Task>.

Which reminds me of something else: you can add a custom indexor to any class by overriding the "this" property:
Code:
        public VdfKey this[string name]
        {
            get
            {
                for (int i = 0; i < _Keys.Count; i++)
                {
                    if (_Keys[i].Name.ToLower() == name.ToLower())
                        return _Keys[i];
                }
                return null;
            }
            set
            {
                for (int i = 0; i < _Keys.Count; i++)
                {
                    if (_Keys[i].Name == name)
                        _Keys[i] = value;
                }
            }
        }
        public VdfKey this[int child]
        {
            get { return _Keys[child]; }
            set { _Keys[child] = value; }
        }
In the above example, you could get a VdfKey out of a collection using index or by name. It simplifies code like this:
Code:
 key.Child[name].Child[3].Child[name2].Child[5]
To this:
Code:
key[name][3][name2][5]
Far less to type and more readable to boot. It's really awesome because you can turn literally any class instance into an array using it. For example, plug this into the code above:
Code:
public object this[int property]
{
  get
  {
    switch (property)
    {
       case 0: return _Start;
       case 1: return _Stop;
       case 2: return Duration;
    }
  }
  set
  {
    switch (property)
    {
       case 0: _Start = (DateTime)value;
       case 1: _Stop = (DateTime)value;
       // Duration is not writable and is calculated on the fly so there is nothing to set for it.
    }
  }
}
And you could access Duration by simply doing Task[2]. Of course, it isn't as fast as .Duration but still neat none-the-less.
 
Last edited:
Joined
May 27, 2008
Messages
3,628 (0.62/day)
System Name Ultra 64
Processor NEC VR4300 (MIPS R4300i)
Motherboard proprietary design
Cooling Fanless aircooled
Memory 4.5MB 250 MHz RDRAM
Video Card(s) 62.5 MHz Reality Coprocessor
Storage 32 - 512 Mbit ROM Cartridge
Display(s) 720x576
Case Clear Blue Funtastic
Audio Device(s) 16-bit CD quality
Power Supply proprietary design
Mouse N64 mouse for use with N64DD
Keyboard N64 keyboard for use with N64DD
That is fantastic thanks for such a comprehensive write up. That's why I'm such a huge fan of TPU everyone goes out of their way to give that bit extra help.

That'l make it much easier to understand what im doing and allow me to run through your examples thanks again :)
 

FordGT90Concept

"I go fast!1!11!1!"
Joined
Oct 13, 2008
Messages
26,259 (4.63/day)
Location
IA, USA
System Name BY-2021
Processor AMD Ryzen 7 5800X (65w eco profile)
Motherboard MSI B550 Gaming Plus
Cooling Scythe Mugen (rev 5)
Memory 2 x Kingston HyperX DDR4-3200 32 GiB
Video Card(s) AMD Radeon RX 7900 XT
Storage Samsung 980 Pro, Seagate Exos X20 TB 7200 RPM
Display(s) Nixeus NX-EDG274K (3840x2160@144 DP) + Samsung SyncMaster 906BW (1440x900@60 HDMI-DVI)
Case Coolermaster HAF 932 w/ USB 3.0 5.25" bay + USB 3.2 (A+C) 3.5" bay
Audio Device(s) Realtek ALC1150, Micca OriGen+
Power Supply Enermax Platimax 850w
Mouse Nixeus REVEL-X
Keyboard Tesoro Excalibur
Software Windows 10 Home 64-bit
Benchmark Scores Faster than the tortoise; slower than the hare.
Oh, and another thing. If Duration is going to be accessed a lot but its value changed infrequently, you can make the setter properties on Start and Stop update a _Duration variable that is simply read:
Code:
using System;

public class Task
{
  private DateTime _Start = new DateTime();
  public DateTime Start
  {
    get { return _Start; }
    set
    {
      _Start = value;
      if ((_Stop != default(DateTime)) && (_Stop > _Start))
        _Duration = _Stop - _Start;
    }
  }

  private DateTime _Stop = new DateTime();
  public DateTime Stop
  {
    get { return _Stop; }
    set
    {
      _Stop = value;
      if ((_Start != default(DateTime)) && (_Stop > _Start))
        _Duration = _Stop - _Start;
    }
  }

  private TimeSpan _Duration = new TimeSpan();
  public TimeSpan Duration
  {
    get { return _Duration; }
  }

  public Task() { }
  public Task(DateTime start, DateTime stop)
  {
    _Start = start;
    Stop = stop; // modify this to use the setter in order to update _Duration.
  }
}
If you did .Start = DateTime.Now, .Duration would remain default(TimeSpan); if you did .Stop = DateTime.Now after that, .Duration would contain the difference between the two. It ignores changes unless both are not default making it easy to check Duration for whether or not it ran at all.

Edit: There is a chance that Start may be submitted after Stop in a case where Start and Stop are already set. It would result in a negative value in Duration which is improper. If such is the case, I added a comparison to both setters to make sure Duration will never be negative.
 
Last edited:
Top