Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding how many times an instance happens in a list

Tags:

c#

list

I have a list and my goal is to determine how many times the values in that list goes above a certain value.

For instance if my list is: List = {0, 0, 3, 3, 4, 0, 4, 4, 4} Id like to know that there were two instances where my values in the list were greater than 2 and stayed above 2. So in this case there were 2 instances, since it dropped below 2 at one point and went above it again.

    private void Report_GeneratorButton_Click(object sender, EventArgs e)
    {
        //Lists
        var current = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.Current].ToList();
        var SOC = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.Soc].ToList();
        var highcell = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.HighestCell].ToList();
        var lowcell = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.LowestCell].ToList();

        //Seperates current list into charging, discharging, and idle
        List<double> charging = current.FindAll(i => i > 2);
        List<double> discharging = current.FindAll(i => i < -2);
        List<double> idle = current.FindAll(i => i < 2 && i > -2);

        //High cell
        List<double> overcharged = highcell.FindAll(i => i > 3.65);
        int ov = overcharged.Count;

        if (ov > 1)
        {
            Console.WriteLine("This Battery has gone over Voltage!");
        }

        else
        {
            Console.WriteLine("This battery has never been over Voltage.");
        }

        //Low cell
        List<double> overdischarged = lowcell.FindAll(i => i > 3.65);
        int lv = overdischarged.Count;

        if (lv > 1)
        {
            Console.WriteLine("This Battery has been overdischarged!");
        }

        else
        {
            Console.WriteLine("This battery has never been overdischarged.");
        }


        //Each value is 1 second
        int chargetime = charging.Count;
        int dischargetime = discharging.Count;
        int idletime = idle.Count;


        Console.WriteLine("Charge time: " + chargetime + "s" + "\n" + "Discharge time: " + dischargetime + "s" + "\n" + "Idle time: " + idletime);

    }

My current code is this and outputs:

    This battery has never been over Voltage.
    This battery has never been overdischarged.
    Charge time: 271s
    Discharge time: 0s
    Idle time: 68
like image 635
Andrew Lerma Avatar asked Dec 23 '25 00:12

Andrew Lerma


2 Answers

There are a great many ways to solve this problem; my suggestion is that you break it down into a number of smaller problems and then write a simple method that solves each problem.

Here's a simpler problem: given a sequence of T, give me back a sequence of T with "doubled" items removed:

public static IEnumerable<T> RemoveDoubles<T>(
  this IEnumerable<T> items) 
{
  T previous = default(T);
  bool first = true;
  foreach(T item in items)
  {
    if (first || !item.Equals(previous)) yield return item;
    previous = item;
    first = false;
  }
}

Great. How is this helpful? Because the solution to your problem is now:

int count = myList.Select(x => x > 2).RemoveDoubles().Count(x => x);

Follow along.

If you have myList as {0, 0, 3, 3, 4, 0, 4, 4, 4} then the result of the Select is {false, false, true, true, true, false, true, true, true}.

The result of the RemoveDoubles is {false, true, false, true}.

The result of the Count is 2, which is the desired result.

Try to use off-the-shelf parts when you can. If you cannot, try to solve a simple, general problem that gets you what you need; now you have a tool you can use for other tasks that require you to remove duplicates in a sequence.

like image 76
Eric Lippert Avatar answered Dec 24 '25 13:12

Eric Lippert


This solution should achieve the desired result.

    List<int> lsNums = new List<int>() {0, 0, 3, 3, 4, 0, 4, 4, 4} ;
    public void MainFoo(){
        int iChange = GetCritcalChangeNum(lsNums, 2);
        Console.WriteLine("Critical change = %d", iChange);
    }
    public int GetCritcalChangeNum(List<int> lisNum, int iCriticalThreshold) { 
        int iCriticalChange = 0;
        int iPrev = 0;
        lisNum.ForEach( (int ele) => { 
            if(iPrev <= iCriticalThreshold && ele > iCriticalThreshold){
                iCriticalChange++;
            }
            iPrev = ele;
        });

        return iCriticalChange;
    }
like image 35
Cabbage Champion Avatar answered Dec 24 '25 14:12

Cabbage Champion



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!