1

I am having problems with arrays, mainly I am looking for a way to remove a sub array from an array but with an exact sequence. For example:

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

The result would be:

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

So as you see it would remove only {3, 4, 5} as a sequence not a separate value, values 3, 5 are kept in a greater array.

I've done it with the to string conversion and cutting sub strings, but there probably is an easier and more elegant way.

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
Wojciech Szabowicz
  • 3,646
  • 5
  • 43
  • 87

6 Answers6

1
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();
}

First store all the inexes where greaterArray has first element of lesserArray. Then check for next and next to next till the length of allIndex. if all these values are equal to the lesserArray values sequentially then We will set values on these indexes in greaterArray as 0. Finally We will remove all the 0 from greaterArray.

Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
1
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's answer above removes the pattern just once. Though this gives the correct answer, the indices logic can be replaced by something more elegant.

Sahil Lakhwani
  • 108
  • 2
  • 11
1

This does precisely what you want and works with all data type arrays.

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

Or

/// <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);
}
Jared Shue
  • 11
  • 1
0

I have made a simple solution for you. it is not a very well optimized. but you can take the idea from it.

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

I make the iteration only for the difference between two arrays. then I skip the i then take the length of the second array then compare it to the first array. if they are equal. It will take the first elements of the first array and concatenated to the rest of elements of the first array.

You can enhance this method performance. Hope you get the idea.

Nadeem Khoury
  • 886
  • 6
  • 18
0

try this

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();
0

You can use ArraySegment to have a better understanding of you algo :

    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();
    }
MSE
  • 327
  • 3
  • 8