我有一个列表,我的目标是确定列表中的值超过特定值多少次。
例如,如果我的列表是: 列表= {0,0,3,3,4,4,0,4,4,4} 我想知道有两个实例,我的列表中的值大于2并保持在2以上。因此,在这种情况下,有2个实例,因为它一次下降到2以下并再次高于它。
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);
}
我当前的代码是这样,并输出:
This battery has never been over Voltage.
This battery has never been overdischarged.
Charge time: 271s
Discharge time: 0s
Idle time: 68
答案 0 :(得分:4)
有很多方法可以解决此问题;我的建议是,将其分解为许多较小的问题,然后编写解决每个问题的简单方法。
这是一个更简单的问题:给定T
的序列,给我返回T
的序列,其中删除了“加倍”项:
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;
}
}
太好了。这有什么帮助?因为现在您的问题的解决方案是:
int count = myList.Select(x => x > 2).RemoveDoubles().Count(x => x);
继续。
如果您将myList
作为{0, 0, 3, 3, 4, 0, 4, 4, 4}
,则Select
的结果为{false, false, true, true, true, false, true, true, true}
。
RemoveDoubles
的结果为{false, true, false, true}
。
Count
的结果为2,这是期望的结果。
请尽可能使用现成的零件。如果无法解决,请尝试解决一个简单,通用的问题,该问题将为您提供所需的东西。现在您有了一个可用于其他任务的工具,这些任务需要您按顺序删除重复项。
答案 1 :(得分:2)
此解决方案应达到期望的结果。
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;
}
答案 2 :(得分:1)
您可以创建如下所示的扩展方法。
public static class ListExtensions
{
public static int InstanceCount(this List<double> list, Predicate<double> predicate)
{
int instanceCount = 0;
bool instanceOccurring = false;
foreach (var item in list)
{
if (predicate(item))
{
if (!instanceOccurring)
{
instanceCount++;
instanceOccurring = true;
}
}
else
{
instanceOccurring = false;
}
}
return instanceCount;
}
}
并使用这种新创建的方法
current.InstanceCount(p => p > 2)
答案 3 :(得分:0)
public static int CountOverLimit(IEnumerable<double> items, double limit)
{
int overLimitCount = 0;
bool isOverLimit = false;
foreach (double item in items)
{
if (item > limit)
{
if (!isOverLimit)
{
overLimitCount++;
isOverLimit = true;
}
}
else if (isOverLimit)
{
isOverLimit = false;
}
}
return overLimitCount;
}
答案 4 :(得分:0)
这是一个相当简洁易读的解决方案。希望这会有所帮助。如果限制是可变的,只需将其放在函数中,然后将列表和限制作为参数即可。
int [] array = new int [9]{0, 0, 3, 1, 4, 0, 4, 4, 4};
List<int> values = array.ToList();
int overCount = 0;
bool currentlyOver2 = false;
for (int i = 0; i < values.Count; i++)
{
if (values[i] > 2)
{
if (!currentlyOver2)
overCount++;
currentlyOver2 = true;
}
else
currentlyOver2 = false;
}
答案 5 :(得分:0)
使用System.Linq
进行此操作的另一种方法是遍历列表,同时选择item
本身和index
,然后为每个项目返回true
项目大于value
,并且前一项小于或等于value
,然后选择true
个结果数。当然,对于索引0
有一种特殊情况,其中我们不检查上一项:
public static int GetSpikeCount(List<int> items, int threshold)
{
return items?
.Select((item, index) =>
index == 0
? item > threshold
: item > threshold && items[index - 1] <= threshold)
.Count(x => x == true) // '== true' is here for readability, but it's not necessary
?? 0; // return '0' if 'items' is null
}
样品用量:
private static void Main()
{
var myList = new List<int> {0, 0, 3, 3, 4, 0, 4, 4, 4};
var count = GetSpikeCount(myList, 2);
// count == 2
}