Anil Gadiyar
Anil Gadiyar

Reputation: 397

Replace byte 10 by 10 10

Hi I want to replace a byte[] where ever there is 10 by 10 10. here is my code. if i have my data as "10 20 10 20 40 50 50 50 50 10 03" i want to replce it by "10 20 10 10 20 40 50 50 50 50 10 10 03" note: first byte is untouched plse follow my comment, my idea is to push the byte array to nxt position and add another 10.

 foreach (var b in command.ToBytes()) 
                {

                   // var c = b;
                    transmitBuffer[count++] = b;  data is formed here
                    addedbuffer[addall++] = b;     duplication is made
                }
                if (addedbuffer[0] == 16 && addedbuffer[1] == 32 || addedbuffer[50] == 16 && addedbuffer[51] == 03)           /
                    {
/condition on which to enter here
                        addedbuffer[0] = 0;  //making 1st and 2nd value as null
                        addedbuffer[1] = 0;
                        for (int i = 0; i < addedbuffer.Length; i++) //till length i will chk 
                        {
                            if (addedbuffer[i] == 10) //replace 10  by 10 10 
                                addedbuffer[i] = 1010; // error,
                        }




        }

Upvotes: 3

Views: 255

Answers (4)

w.b
w.b

Reputation: 11228

This works via conversion to strings, using String.Replace and converting back:

byte[] source = new Byte[] { 20, 10, 20, 40, 50, 50, 50, 50, 10, 03 };

string[] strArr = Array.ConvertAll(source, b => b.ToString());
string[] replArr = String.Join(" ", strArr).Replace("10", "10 10").Split();

byte[] newArr = Array.ConvertAll(replArr, str => Byte.Parse(str));

Edit:

Another approach with LINQ - elements at first and last indexes and all elements not equal to 10 are unchanged, for all remaining 10s it returns a sequence of 2 10s:

byte[] res = source.SelectMany((b, index) => index == 0 
                                             || index == source.Length - 1      
                                             || b != 10 ? 
                               Enumerable.Repeat(b, 1) : Enumerable.Repeat(b, 2))
                   .ToArray();

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186708

You can't insert into array (you can do it with List<T>), so it looks that you have to create a new array; Linq solution:

  Byte[] source = new Byte[] {
    20, 10, 20, 40, 50, 50, 50, 50, 10, 03
  };

  var result = source
    .SelectMany((item, index) => 
       item == 10 && index != 0 ? new Byte[] { item, item } : new Byte[] { item })
    .ToArray();

However, using List<Byte> (in order just to insert 10's) instead of Byte[] is a better way out:

  List<Byte> list = List<Byte>() {
    20, 10, 20, 40, 50, 50, 50, 50, 10, 03
  };

  // In order not to read inserted 10's we loop backward 
  // i >= 1: 1st byte should be preserved as is even if its == 10
  for (int i = list.Count - 1; i >= 1; --i)
    if (list[i] == 10)
      list.Insert(i + 1, 10);

Upvotes: 4

Matthew Watson
Matthew Watson

Reputation: 109577

This is a fairly efficient way to do it (requires two passes over the input array, but does not require any resizing of the output array):

public static byte[] Replace10With1010ExcludingFirstByte(byte[] input)
{
    //  Count 10s excluding first byte.
    int count = input.Skip(1).Count(b => b == 10);

    // Create output array of appropriate size.
    byte[] result = new byte[input.Length +  count];

    // Copy input to output, duplicating all 10s that are not the first byte.

    result[0] = input[0];

    for (int i = 1, j = 1; i < input.Length; ++i, ++j)
    {
        result[j] = input[i];

        if (input[i] == 10)
            result[++j] = 10;
    }

    return result;
}

Call it with your original array, and use the returned array instead.

Test code (for use in a Console app):

byte[] input = {10, 20, 10, 20, 40, 50, 50, 50, 50, 10, 03};
var result = Replace10With1010ExcludingFirstByte(input);
Console.WriteLine(string.Join(", ", result));

[EDIT] It seems from one of your comments to another answer that you also want to also exclude the last byte from conversion too.

If so, use this code instead:

public static byte[] Replace10With1010ExcludingFirstAndLastByte(byte[] input)
{
    //  Count 10s excluding first and last byte.
    int count = input.Skip(1).Take(input.Length-2).Count(b => b == 10);

    // Create output array of appropriate size.
    byte[] result = new byte[input.Length +  count];

    // Copy input to output, duplicating all 10s that are not the first byte.

    result[0] = input[0];

    for (int i = 1, j = 1; i < input.Length; ++i, ++j)
    {
        result[j] = input[i];

        if ((input[i] == 10) && (i != (input.Length-1)))
            result[++j] = 10;
    }

    return result;
}

Upvotes: 0

codekaizen
codekaizen

Reputation: 27419

It helps to think of sequences like arrays (IEnumerable<T> in C#) as things that can be transformed into new sequences. Much like numbers can be transformed when you send them into a function, sequences can be, too.

Consider if I have a function that is defined as Add10If10(Byte b). It might looks like this:

public static Byte Add10If10(Byte b)
{
    if (b == 10)
    {
        return b + 10;
    }

    return b;
}

Numbers which go into this are transformed based on the condition, and come out either 10 larger or the same. The same can be done with sequences, you can take a sequence with some number of elements, and transform it so it has more elements. The result is a new sequence:

public static IEnumerable<Byte> AddAdditional10If10(IEnumerable<Byte> values)
{
    foreach (var b in values)
    {
        if (b == 10)
        { 
            yield return 10;
        }

        yield return b;
    }
}

This function returns an additional 10 for every 10 it encounters. Now that you have the right sequence, you can change how it is stored by changing it to an array:

AddAdditional10If10(addedbuffer).ToArray();

Upvotes: 2

Related Questions