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

时间:2011-04-11 19:12:48

标签: c# list

所以我有一个项目清单。列表中的每个项目都有一个名为notional的属性。现在,列表已经排序。我需要做的是,开发一个将列表类型设置为以下之一的函数:

  • 子弹 - notional对于每个项目都是相同的
  • 分期偿还 - notional在整个计划过程中减少(可能在元素之间保持不变但它永远不会上升,并且应该结束)
  • Accreting - notional在整个计划过程中增加(可能在元素之间保持不变但它应该永远不会下降,并且应该结束更高)
  • 过山车 - notional上升和下降(可以结束相同,更高或更低,但不应该对每个元素都相同,不应该像其他类型一样分类)

这种方法看起来会是什么样的,以及通过列表找出问题的最有效方法是什么?

谢谢!

6 个答案:

答案 0 :(得分:1)

这将是一种直接的方式:

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;

答案 1 :(得分:1)

  1. 让trendOut = Bullet
  2. 从第一项循环到最后一项

    2.1。如果以前是名义上的&lt;下一个概念

      2.1.a.  If trendOut = Amortizing return RollerCoaster 
      2.1.b.  Else set trendOut = Accreting
    

    2.2。如果以前的名义&gt;下一个概念

      2.2.a.  If trendOut = Accreting return RollerCoaster
      2.2.b.  Else set trendOut = Amortizing
    
  3. return trendOut。

答案 2 :(得分:0)

你可以做一些像这个简单的事情

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;
}

答案 3 :(得分:0)

我通常首先通过优化简化然后再进行性能优化。因此,我首先制作第二个N-1元素列表,其{元素}是第一个列表的{notionals}之间的差异。

因此,对于第二个列表,我希望以下列出您的需求

  • 子弹 - 所有元素均为0
  • 摊销 - 所有元素保持0或负数
  • Accreting - 所有元素保持为0或正数
  • 过山车 - 元素在负极和负极之间振荡。阳性

你可以在一次通过中优化它。基本上,这是对数据的独立区分。

答案 4 :(得分: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";
        }

答案 5 :(得分:0)

这基本上是Linq对丹麦语答案的实现。它需要(最坏的情况)3次通过列表,但因为它们非常小,从性能的角度来看并不重要。 (我将其编写为int列表,因此您必须轻松修改它才能使用您的类型。

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将是包含以下内容的元组:

  1. 集合的最后一个元素(没用)
  2. Item2将包含一个布尔值,指示是否有任何元素大于前一个元素
  3. Item3将包含一个布尔值,指示是否有任何元素小于前一个元素
  4. 可以使用与上面相同的switch语句来确定数据遵循的模式。