如何确定列表中是否有 6 个连续的降序数字?

How can I find if there are 6 consecutive descending numbers in a List?

提问人:tcode 提问时间:9/22/2023 更新时间:9/22/2023 访问量:63

问:

我必须检索对象列表,然后将这些对象作为可视化图表的数据传递。在遍历 List 时,我需要检查是否有 6 个连续对象具有 ChartVal 属性的递减值。如果是这种情况,则每个对象都必须将其 DataPointColour 设置为“Red”,否则设置为“Black”。

public class ChartData
{
  public int ChartVal {get; set;}
  public string ChartColour {get; set;}
  //Other properties
}

IList<ChartData> dataForChart = new List<ChartData>();
var data = _myDataService.GetChartData();

foreach(var item in data)
{
  //Pseudo code
  //Determine if current item.ChartVal is less than previous item.ChartVal
  //If so, set ChartColour to Red, but only if the current item.ChartVal is part
  //of a consecutive group of 6 decreasing values

dataForChart.Add(new ChartData { ChartVal = item.Value, ChartColour = 'Red' });

//Else, ChartColour is Black

dataForChart.Add(new ChartData { ChartVal = item.Value, ChartColour = 'Black' });

}

我很难知道从哪里开始,主要是因为对象 ChartColour 必须是红色,但前提是它是连续的降序图表组的一部分。

例子:

如果 var 数据包含 [10,9,8,7,6,5,5,6,7,8],则数字序列 10,9,8,7,6,5 将在图表上以红色突出显示,数字 5,6,7,8 将为黑色。

如果有人能帮忙,我将不胜感激。

非常感谢。

C# 列表 LINQ

评论

1赞 jmcilhinney 9/22/2023
如果项目小于前一个项目,则需要将项目保留在子列表中。每次遇到没有较低值的项目时,请清除子列表并重新开始当前项目。子列表包含六个项目后,设置其颜色。人们在这样的事情上遇到麻烦的原因是,他们试图在代码中思考,而不是在逻辑中思考,然后在代码中实现该逻辑。在你已经知道它必须做什么之前,不要尝试编写任何代码,即不仅仅是最终结果,还有获得它们的步骤。
0赞 tcode 9/28/2023
@jmcilhinney - 谢谢,这个建议是最有帮助的。

答:

2赞 Febre 9/22/2023 #1

如何创建一个 ColourState 类来代替字符串。通过这种方式,您可以监视下降趋势,如果它超过 6,您可以更新状态类的 color 属性,并且该集的所有项目部分都将更改。

请参阅下面的示例。

public class ChartData
{
  public int ChartVal {get; set;}
  public ColourState ChartColour {get; set;}
  //Other properties
}

public class ColourState
{
    public string Colour { get; set; } = "Black";
}

IList<ChartData> dataForChart = new List<ChartData>();
var data = _myDataService.GetChartData();

int previousValue = int.MinValue;
int count = 0;
var state = new ColourState();
foreach(var item in data)
{
  if(item.Value < previousValue){
    count++;
  }
  else
  {
    count = 0;
    state = new ColourState();
  }

  if(count >= 6){
    state.Colour = "Red";
  }

  var chartData = new ChartData
  {
    ChartVal = item.Value,
    ChartColour = state
  };

    dataForChart.Add(chartData);
    previousValue = item.Value;
}

1赞 JonasH 9/22/2023 #2

想想你的问题。首先,您需要比较两个连续的项目。然后你需要检查这两个项目是否是降序的,以及一些方法来计算顺序降序数字的数量。如果您上升并且计数高于 6,则您找到了一个范围,您需要将颜色涂成红色,然后重置计数。

例如:

public static IEnumerable<(int Index, int Length)> GetDescendingRanges(
    IEnumerable<int> values,
    int minSequenceLength)
{
    
    using var iter = values.GetEnumerator();
    if (!iter.MoveNext())
    {
        yield break;
    }
    var previousValue = iter.Current;
    var currentIndex = 1;
    var sequenceStartIndex = 0;
    var sequenceLength = 0;
    while (iter.MoveNext())
    {
        var currentValue = iter.Current;
        sequenceLength++;
        if (currentValue < previousValue)
        {
            if (sequenceLength == 0)
            {
                sequenceStartIndex = currentIndex-1;
            }
        }
        else
        {
            if (sequenceLength >= minSequenceLength)
            {
                yield return ( sequenceStartIndex, sequenceLength);
            }
            sequenceLength = 0;
            sequenceStartIndex = currentIndex;
        }

        currentIndex++;
        previousValue = currentValue;
    }
}

这应该为您提供一系列需要涂成红色的范围。最简单的选项可能是将所有 chartData 创建为黑色,然后遍历列表并将所有降序部分涂成红色。

var values = data.Select(item => item.Value);
var chartData = values.Select(v=> new ChartData(){ ChartVal = v, ChartColour = "Black" }).ToArray(); 
foreach(var (offset, length) in GetDescendingRanges(values , 6)){
   for(int i = 0; i < length; i++){
       chartData[offset + i].ChartColour = "Red";
   }
}