查看列表并确定趋势的功能

所以我有一个项目清单。列表中的每个项目都有一个名为
notional
的属性。现在,列表已经排序。我需要做的是,开发一个将列表类型设置为以下之一的函数: Bullet -
notional
对于每个项目都是相同的 摊销 -
notional
在计划的过程中减少(可能在元素之间保持不变但它应该永远不会上升,并且应该结束) Accreting -
notional
在整个计划过程中增加(可能在元素之间保持不变但它应该永远不会下降,并且应该结束更高) 过山车 -
notional
上下移动(可以结束相同,更高或更低,但每个元素不应该相同,不应该像其他类型一样分类) 这个方法会是什么样子,最有效的方法是通过列表来解决这个问题? 谢谢!     
已邀请:
这将是一种直接的方式:
bool hasGoneUp = false;
bool hasGoneDown = false;
T previous = null; // T is the type of objects in the list; assuming ref type

foreach(var item in list)
{
    if (previous == null) {
        previous = item;
        continue;
    }

    hasGoneUp = hasGoneUp || item.notional > previous.notional;
    hasGoneDown = hasGoneDown || item.notional < previous.notional;

    if(hasGoneUp && hasGoneDown) {
        return Trend.Rollercoaster;
    }

    previous = item;
}

if (!hasGoneUp && !hasGoneDown) {
    return Trend.Bullet;
}

// Exactly one of hasGoneUp and hasGoneDown is true by this point
return hasGoneUp ? Trend.Accreting : Trend.Amortizing;
    
让trendOut = Bullet 从第一项循环到最后一项 2.1。如果以前是名义上的&lt;下一个概念
  2.1.a.  If trendOut = Amortizing return RollerCoaster 
  2.1.b.  Else set trendOut = Accreting
2.2。如果以前的名义>下一个名义
  2.2.a.  If trendOut = Accreting return RollerCoaster
  2.2.b.  Else set trendOut = Amortizing
回归趋势。     
你可以做一些像这样简单的事情
var changeList = new List<Integer>
for(i = 0; i < yourList.Count() - 1; i++)
{
    changeList.Add(yourList.Item(i + 1) - yourList.Item(i));
}

//Determine if the nature of the list

var positiveChangeCount = changeList.Where(x => x < 0);
var negativeChangeCount = changeList.Where(x => X > 0);

if (positiveChangeCount = yourList.Count)
{
   Accreting;
}
elseif (negativeChangeCount = yourList.Count)
{
   Amortizing;
}
elseif (negativeChangeCount + PositiveChangeCount = 0)
{
  Bullet;
}
else
{
  Rollercoaster;
}
    
我通常首先通过优化简化然后再进行性能优化。因此,我首先制作N-1个元素的第二个列表,其{元素}是第一个列表的{notionals}之间的差异。 因此,对于第二个列表,我希望以下列出您的需求 子弹 - 所有元素都是0 摊销 - 所有元素保持0或负数 Accreting - 所有元素保持0或正数 过山车 - 元素在负极和负极之间振荡。正 您可以在一次通过中优化它。基本上,这是对数据的独立区分。     
        bool OnlyGreaterOrEqual=true;
        bool OnlyLessOrEqual=true;  

        foreach(int i=1;i<itemList.Count;i++){
            if(itemList[i].notional>itemList[i-1].notional){
                OnlyLessOrEqual=false;
            }else if(itemList[i].notional<itemList[i-1].notional){
                OnlyGreaterOrEqual=false;
            }
        }

        if(OnlyGreaterOrEqual && OnlyLessOrEqual){
            return "Bullet";
        }else if(OnlyGreaterOrEqual){
            return "Accreting":
        }else if(OnlyLessOrEqual){
            return "Amortizing";
        }else{
            return "RollerCoast";
        }
    
这基本上是Linq对丹麦语答案的实现。它需要(最坏的情况)3次通过列表,但因为它们非常小,从性能的角度来看并不重要。 (我把它写在
int
s列表上,所以你必须轻松地修改它才能使用你的类型)。
var tmp = values
            .Skip(1)
            .Zip( values, (first, second) => first - second )
            .ToList();

var up = tmp.Any( t => t > 0 );
var down = tmp.Any( t => t < 0 );

if( up && down )
    // Rollercoaster
else if( up )
    // Accreting
else if( down )
    // Amortizing
else 
    // Bullet
您也可以(ab)使用
Aggregate
运算符和
Tuple
作为一个查询。但是,如果集合为空并且在生产代码中使用有点奇怪,则会失败。
var result = values.Skip(1).Aggregate( 
             Tuple.Create<int, bool, bool>( values.First(), false, false ),
             ( last, current ) => {
                 return Tuple.Create( 
                     current, 
                     last.Item2 || (current - last.Item1) > 0,
                     last.Item3 || (current - last.Item1) < 0 );
             });
result
将是一个包含以下内容的元组: 集合的最后一个元素(没用)
Item2
将包含一个布尔值,指示是否有任何元素大于前一个元素
Item3
将包含一个布尔值,指示是否有任何元素小于前一个元素 可以使用与上面相同的switch语句来确定数据遵循的模式。     

要回复问题请先登录注册