从数组中删除精确的子数组值

本文关键字:数组 删除 | 更新日期: 2023-09-27 18:15:08

我在数组方面遇到了问题,主要是我在寻找一种从数组中删除子数组的方法,但要使用精确的序列。例如:

int[] greaterArray = {8, 3, 4, 5, 9, 12, 6, 3, 5}
int[] lesserArray = {3, 4, 5}

结果是:

int[] resultArray = {8, 9, 12, 6, 3, 5}

因此,正如您所看到的,它将只删除{3,4,5}作为一个序列,而不是一个单独的值,值3,5保留在一个更大的数组中。

我已经完成了到字符串的转换和剪切子字符串,但可能有一种更简单、更优雅的方法。

从数组中删除精确的子数组值

private static int[] RemoveSubArray()
{
    int[] greaterArray = {8, 3, 4, 5, 9, 12, 6, 3, 5, 3, 4, 5};
    int[] lesserArray = {3,4,5};
    if (lesserArray == null || lesserArray.Length == 0)
    {
        return greaterArray;
    }
    int[] allIndex = greaterArray.Select((b,i) => b == lesserArray[0] ? i : -1).Where(i => i != -1).ToArray();
    for (int index = 0; index < allIndex.Length; index++)
    {
        int count = 0;
        for (int x = 1; x < allIndex.Length; x++)
        {
            if (greaterArray[allIndex[index] + x] == lesserArray[x])
            {
                count++;
            }
        }
        if (count == allIndex.Length - 1)
        {
            for (int inner = 0; inner < allIndex.Length; inner++)
            {
                greaterArray[allIndex[index] + inner] = 0;
            }
        }
    }
    return greaterArray = greaterArray.Where(i => i != 0).ToArray();
}

首先存储greaterArray具有lesserArray的第一个元素的所有不精确。然后检查next和next-to-next,直到allIndex的长度。如果所有这些值顺序地等于lesserArray值,那么我们将把greaterArray中这些索引的值设置为0。最后,我们将从greaterArray中删除所有的0。

static int[] Run(int[] greaterArray, int[] lesserArray)
{
    int[] result = new int[greaterArray.Length];
    int k = 0;
    for (int i = 0; i < greaterArray.Length; )
    {
        if (greaterArray.Skip(i).Take(lesserArray.Length).SequenceEqual(lesserArray))
        {
            i += lesserArray.Length;
        }
        else
        {
            result[k] = greaterArray[i];
            i++;
            k++;
        }           
    }
    return result;
}

Nadeem上面的回答只删除了一次模式。尽管这给出了正确的答案,但索引逻辑可以被更优雅的东西取代。

这正是您想要的,并且适用于所有数据类型数组。

/// <summary>
/// Removes all occurrences of the specified collection from the referenced array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="array"></param>
/// <param name="collection"></param>
public static void RemoveAll<T>(ref T[] array, T[] collection)
{
    T[] result = { };
    for (int i = 0; i < array.Length; i++)
    {
        T[] chunk = new T[collection.Length];
        for (int j = 0; j < chunk.Length; j++)
            if (!((i + j) >= array.Length))
                chunk[j] = array[i + j];
        bool match = true;
        for (int j = 0; j < chunk.Length; j++) { if (!Equals(chunk[j], collection[j])) { match = false; break; } }

        if (!match) {
            Array.Resize(ref result, result.Length + 1);
            result[result.Length - 1] = chunk[0];
        }
        else i += collection.Length - 1;
    }
    array = result;
}

/// <summary>
/// Removes a collection of the specified index count at the specified index from the referenced array.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="array"></param>
/// <param name="size"></param>
/// <param name="index"></param>
public static void Remove<T>(ref T[] array, int count, int index)
{
    if (index + count >= array.Length || index >= array.Length || count > array.Length) { throw new ArgumentOutOfRangeException(); }
    for (int i = 0; i < array.Length; i++) { if (i == index) i += count - 1; else if (i - count >= 0) array[i - count] = array[i]; }
    Array.Resize(ref array, array.Length - count);
}

我为您提供了一个简单的解决方案。它不是一个很好的优化。但你可以接受它的想法。

 static int[] Run(int[] greaterArray, int[] lesserArray)
        {
            for (int i = 0; i <= greaterArray.Length - lesserArray.Length; i++)
            {
                if (greaterArray.Skip(i).Take(lesserArray.Length).SequenceEqual(lesserArray))
                {
                    return greaterArray.Take(i).Concat(greaterArray.Skip(i + lesserArray.Length)).ToArray();
                }
            }
            return greaterArray;
        }

我只针对两个数组之间的差异进行迭代。则我跳过CCD_ 1,然后取第二阵列的长度。如果它们相等。它将采用第一个数组的第一个元素,并连接到第一个数组中的其余元素。

您可以增强此方法的性能。希望你明白。

尝试这个

int[] greaterArray = { 8, 3, 4, 5, 9, 12, 6, 3, 5 };
int[] lesserArray = { 3, 4, 5 };
int[] resultArray = string.Join(",", greaterArray).Replace(string.Join(",", lesserArray), "").Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(p => Convert.ToInt32(p)).ToArray();

您可以使用ArraySegment更好地了解您的算法:

    static void Main(string[] args)
    {
        int[] array = {8, 3, 4, 5, 9, 12, 6, 3, 5};
        int[] subArray = {3, 4, 5};
        int arrayLength = array.Length;
        int subArrayLength = subArray.Length;
        ArraySegment<int> segment = new ArraySegment<int>();
        bool found = false;
        for (int i = 0; i < arrayLength - subArrayLength; i++)
        {
            segment = new ArraySegment<int>(array, i, subArrayLength);
            // look for sub array
            int nbFound = 0;
            for (int j = 0; j < subArrayLength; j++)
            {
                if (segment.Array[segment.Offset + j] == subArray[j])
                    ++nbFound;
                else
                    break;
            }
            // sub array found
            if (nbFound == subArrayLength)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            int[] result = new int [arrayLength - subArrayLength];
            Array.Copy(array, 0, result, 0, segment.Offset + 1);
            Array.Copy(array, segment.Offset + subArrayLength, result, segment.Offset + 1, arrayLength - 1 - segment.Offset - subArrayLength);
            Console.WriteLine($"Result : {string.Join(", ", result)}");
        }
        else
        {
            Console.WriteLine($"Result : {string.Join(", ", array)}");
        }
        Console.ReadKey();
    }