C# 给定布尔数组,如何使这些循环更具性能?

C# 给定布尔数组,如何使这些循环更具性能?,c#,arrays,loops,C#,Arrays,Loops,如果您有: bool[] arrayExample = {false, true, false, false, true, true, false, false, true, true, true}; 给定一个n值,我在数组中循环查找哪个索引具有真值 例如:如果n=1:我想返回所有具有1个真值的索引。因此,返回列表将是{1,4,5,8,9,10} 如果n=2:我想返回一个列表,使其索引在一行中有两个真值:{4,8,9} 另外,我想为n=3做这个 是否有更干净/更高效的方法来运行此代码 List

如果您有:

bool[] arrayExample = {false, true, false, false, true, true, false, false, true, true, true};
给定一个n值,我在数组中循环查找哪个索引具有真值

例如:如果n=1:我想返回所有具有1个真值的索引。因此,返回列表将是{1,4,5,8,9,10}

如果n=2:我想返回一个列表,使其索引在一行中有两个真值:{4,8,9}

另外,我想为n=3做这个

是否有更干净/更高效的方法来运行此代码

List<int> indices = new List<int>();
bool counter = false;

if (n == 1)
{
    for (int i = 0; i < arrayExample.Length; ++i)
    {
        if (arrayExample[i])
        {
            indices.Add(i);
        }
    }
}
else if (n == 2)
{
    for (int i = 0; i < arrayExample.Length; ++i)
    {
        if (counter == true && arrayExample[i] == false)
        {
            counter = false;
        }
        if (arrayExample [i])
        {
            if (counter == false)
            {
                counter = true;
            }
            else
            {
                indices.Add(i);
                counter = false;
            }
         }
     }
}
这里有一个想法: 以数组为例:[F,T,F,F,T,T,F,F,T,T,T,T] 从头到尾,标记在每个位置遇到的真值数量:[0,1,0,0,2,1,0,0,3,2,1]。 现在您可以得到任意n的答案:返回每个索引,其中array[index]>=n

如何:

static void Main(string[] args)
{
   bool[] arrayExample = { false, true, false, false, true, true, false, false, true, true, true };
   List<int> result = Foo(1, arrayExample);
   foreach(var num in result)
      Console.WriteLine(num);
   Console.ReadKey();
}
static List<int> Foo(int num,bool[] arr)
{
    List<int> indices = new List<int>();
    int count = 0;
    for (int i = 0; i < arr.Length; i++)
    {
       if(arr[i])
       {
           for (int j = 0; j < num; j++)
           {
               if(!arr[i+j])
               {
                     count = 0;
                     break;
               }
                  count++;
           }
                    if (count > 0)
                        indices.Add(i);
       }
   }
  return indices;
}

代码的速度可能还可以;但是,您可以简化算法

const bool F = false, T = true;
bool[] arrayExample = { F, T, F, F, T, T, F, F, T, T, T };

var indices = new List<int>();
int count = 0;
int n = 2;
int delta = n - 1;

for (int i = 0; i < arrayExample.Length; i++) {
    if (arrayExample[i]) {
        count++;
        if (count >= n)
            indices.Add(i - delta);
    } else
        count = 0;
}
这对任何人都有效。计算遇到的后续真值的数量,并在该计数至少等于所需序列长度时添加索引。因为您需要序列中第一个索引的索引,所以必须减去n-1


该算法直接按升序生成索引,不需要临时数组,也没有嵌套循环。也就是说,它的时间性能为On,这里n代表输入的长度。

我只是想把我的代码放在混合中,无论如何,速度都不足以提供任何有用的见解:

public static IEnumerable<int> TrueIndicesCounter(int counter, List<bool> booleans)
{
    if (counter <= 0) return new List<int>();
    var truths = new List<int>();
    for (var booleanIndex = 0; booleanIndex < booleans.Count; booleanIndex++)
    {
        var boolean = booleans[booleanIndex];
        if (boolean != true) continue;
        if (counter == 1)
        {
            truths.Add(booleanIndex);
            continue;
        }
        var counterIndex = 1;
        var counterSatisfied = false;
        while (counterIndex <= counter)
        {
            var targetBoolean = booleans.ElementAtOrDefault(booleanIndex + counterIndex);
            if (targetBoolean != true) break;
            counterIndex++;
            if (counterIndex != counter) continue;
            counterSatisfied = true;
            break;
        }
        if (counterSatisfied)
            truths.Add(booleanIndex);
    }
    return truths;
}

您可以尝试@Dennis_E给出的想法,如下所示:

int i, j;
int[] rep = new int[arrayExample.Length];
if (rep[arrayExample.Length - 1])
    rep[arrayExample.Length - 1] = 1;
for (i = arrayExample.Length - 2; i >= 0; i--)
    if (arrayExample[i])
        rep[i] = rep[i + 1] + 1;
for (i = 0 ; i < arrayExample.Length; i++)
    if (count == n)
        indices.Add(i);

什么是计数器、间隔和可用性阵列?性能是瓶颈吗?这看起来像意大利面代码,为了清晰起见需要重写,但是除非性能不可接受,否则不要尝试微优化。这段代码给出了正确的答案吗?如果是这样的话,你应该结帐以获得关于如何改进它的反馈。这可能包括如何使您的代码更易于理解,以及如何使用来自C的惯用构造以及优化。间隔只能为1或2?使用linq:int[]results=arrayExample.Selectx,i=>new{x=x,i=i}。其中x=>x.x.Selectx=>x.i.ToArray;我真的很喜欢这种方法。我会看看我是否能编程。非常感谢。