【问题标题】:C# get part of array by array maskC#通过数组掩码获取数组的一部分
【发布时间】:2016-11-28 12:55:03
【问题描述】:

请帮助我。我想通过掩码数组获取数组的一部分。 这是我的代码:

byte[] source = new byte[] {97, 98, 99, 5, 15, 66, 77, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0};
byte[] mask = new byte[] { 102, 0, 102, 0, 102, 0, 102, 0 };
byte[] result = EscapeArray(0, source, mask); 
private byte[] EscapeArray(int startIndex, byte[] source, byte[]mask)
{
   ???
}

EscapeArray 方法的输出将为 97、98、99、5、15、66、77。 源数组有任何值,但某处是掩码序列。 EscapeArray 返回从 startIndex 到掩码开头的部分数组。 我需要非常快速的算法,因为这种方法会经常执行。 谢谢

【问题讨论】:

  • 您应该提出一个问题并提供您迄今为止所尝试的内容。
  • 对不起。这个问题是:EscapeArray的实现方法是什么?
  • 这里没有足够的关于数据的信息来提供“非常快”的算法。充其量可以进行具有一些优化的天真的蛮力算法。例如,如果对于大量查询,掩码或源是静态的,则可能会应用比简单的暴力破解更合适的数据结构,但这里没有关于此的信息。
  • 根据您的示例以及我如何解释您的问题,为什么输出不是:“97, 98, 99, 5,15, 66, 77, 102, 0”。如果您将掩码视为“必须完全按照此顺序”,那么您的源确实包含该掩码,但其中有一个额外的“102, 0”,为什么还要将其删除?哦“startIndex to start of mask”...忽略
  • 数组不是适合添加/删除的数据结构

标签: c# arrays


【解决方案1】:

我建议找到第一个掩码出现的索引:

private static int MaskIndex(byte[] source, byte[] mask) {
  if (mask.Length == 0)
    return 0; // or source.Length; or throw exception

  for (int i = 0; i < source.Length - mask.Length + 1; ++i) {
    bool found = true;

    for (int j = 0; j < mask.Length; ++j)
      if (source[i + j] != mask[j]) {
        found = false;

        break;
      }

    if (found)
      return i;
  }

  return source.Length;
}

有了这个你就可以实现EscapeArray as

private byte[] EscapeArray(int startIndex, byte[] source, byte[] mask) {
  int n = MaskIndex(source, mask);

  if (startIndex > n)
    return new byte[0]; // or throw exception 

  return source.Skip(startIndex).Take(n - startIndex).ToArray();
}

测试:

byte[] source = new byte[] 
  { 97, 98, 99, 5, 15, 66, 77, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0 };
byte[] mask = new byte[] 
  { 102, 0, 102, 0, 102, 0, 102, 0 };

// 97, 98, 99, 5, 15, 66, 77  
Console.WriteLine(string.Join(", ", EscapeArray(0, source, mask)));

// 97, 98, 99, 5, 15, 66, 77, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0
Console.WriteLine(string.Join(", ", EscapeArray(0, source, new byte[] {123})));

【讨论】:

    【解决方案2】:

    我们去吧。这是根据您已删除的 cmets 构建的。

    public static void Main()
    {       
        int[] arr = new int[] { 1, 2, 3, 4, 5, 0, 0, 0, 0, 7, 8, 9};
        int[] mask = new int[] { 0, 0, 0, 0 };
    
        // Usage
        var subArr = SubArrayTillMask(2, arr, mask);
    
        Console.WriteLine(String.Join(",",subArr));
    }
    
    
    static int[] SubArrayTillMask(int start, int[] array, int[] mask ) 
    {
        var foundPos = -1;
    
        var len = mask.Length;
        var limit = array.Length - len;
        for( var i = 0;  i <= limit;  i++ ) 
        {
            var k = 0;
            for( ;  k < len;  k++ ) {
                if( mask[k] != array[i+k] ) break;
            }
            if( k == len ) foundPos = i;
        }
        if(foundPos == -1)
            return array;
    
        return array.Skip(start).Take(foundPos-start).ToArray();
    }
    

    示例:.Net Fiddle
    性能测试:.Net Fiddle

    结果:在 0.018965 秒内测试了 10000 行。


    致谢:Find an array (byte[]) inside another array?

    【讨论】:

      猜你喜欢
      • 2020-07-26
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 2014-10-10
      • 2013-11-27
      • 1970-01-01
      • 2017-12-31
      • 2021-06-24
      相关资源
      最近更新 更多