43

Given a populated byte[] values in C#, I want to prepend the value (byte)0x00 to the array. I assume this will require making a new array and adding the contents of the old array. Speed is an important aspect of my application. What is the best way to do this?

-- EDIT --

The byte[] is used to store DSA (Digital Signature Algorithm) parameters. The operation will only need to be performed once per array, but speed is important because I am potentially performing this operation on many different byte[]s.

12
  • I'm sorry: by prepend you mean add at position 0 and moving everything else to index + 1? Commented Jul 9, 2012 at 20:04
  • 2
    @AndreCalil - Yes. Prepend means adding to the beginning, as opposed to Append which means adding to the end. Commented Jul 9, 2012 at 20:05
  • I see, thanks for the kindness. Cytinus, you could load this byte[] into a List<byte>, but that wouldn't be the most performatic choice. How much is speed important to you? Commented Jul 9, 2012 at 20:07
  • 2
    C# arrays are static, so you do need to create a copy in order to prepend a value. But you really haven't given enough detail in your question to comment intelligently. What are you trying to accomplish? How large is the array? How often will you update it? Commented Jul 9, 2012 at 20:09
  • Why are you using an array if you need fast inserts? You should be using something like a linked list. Commented Jul 9, 2012 at 20:19

9 Answers 9

53

If you are only going to perform this operation once then there isn't a whole lot of choices. The code provided by Monroe's answer should do just fine.

byte[] newValues = new byte[values.Length + 1]; newValues[0] = 0x00; // set the prepended value Array.Copy(values, 0, newValues, 1, values.Length); // copy the old values 

If, however, you're going to be performing this operation multiple times you have some more choices. There is a fundamental problem that prepending data to an array isn't an efficient operation, so you could choose to use an alternate data structure.

A LinkedList can efficiently prepend data, but it's less efficient in general for most tasks as it involves a lot more memory allocation/deallocation and also looses memory locallity, so it may not be a net win.

A double ended queue (known as a deque) would be a fantastic data structure for you. You can efficiently add to the start or the end, and efficiently access data anywhere in the structure (but you can't efficiently insert somewhere other than the start or end). The major problem here is that .NET doesn't provide an implementation of a deque. You'd need to find a 3rd party library with an implementation.

You can also save yourself a lot when copying by keeping track of "data that I need to prepend" (using a List/Queue/etc.) and then waiting to actually prepend the data as long as possible, so that you minimize the creation of new arrays as much as possible, as well as limiting the number of copies of existing elements.

You could also consider whether you could adjust the structure so that you're adding to the end, rather than the start (even if you know that you'll need to reverse it later). If you are appending a lot in a short space of time it may be worth storing the data in a List (which can efficiently add to the end) and adding to the end. Depending on your needs, it may even be worth making a class that is a wrapper for a List and that hides the fact that it is reversed. You could make an indexer that maps i to Count-i, etc. so that it appears, from the outside, as though your data is stored normally, even though the internal List actually holds the data backwards.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for pointing out O(1) insertion property of LinkedList, especially when compared to O(n) insertion behaviour of List when inserting at the front.
@MonroeThomas While that is true, it's probably not the best option for the reasons I've mentioned. LinkLists just don't scale well for large collection in general, even if you're only performing operations that are "efficient" for that data structure. Just traversing a linked list is actually rather inefficient, even though it's O(n) just like traversing every other data structure out there.
Agreed, in general. I can count on my hands the number of times I've used a linked list in the last five years. The OP simply hasn't posted enough information regarding his use case to determine optimality of storage for his bytes. :)
@MonroeThomas In case you couldn't determine it from my answer, I'd say that a deque is the best fit for his needs. Now if only one already existed in the base library framework (granted googling C# Deque provides a lot of implementations).
24

Ok guys, let's take a look at the perfomance issue regarding this question. This is not an answer, just a microbenchmark to see which option is more efficient.

So, let's set the scenario:

  • A byte array of 1,000,000 items, randomly populated
  • We need to prepend item 0x00

We have 3 options:

  1. Manually creating and populating the new array
  2. Manually creating the new array and using Array.Copy (@Monroe)
  3. Creating a list, loading the array, inserting the item and converting the list to an array

Here's the code:

 byte[] byteArray = new byte[1000000]; for (int i = 0; i < byteArray.Length; i++) { byteArray[i] = Convert.ToByte(DateTime.Now.Second); } Stopwatch stopWatch = new Stopwatch(); //#1 Manually creating and populating a new array; stopWatch.Start(); byte[] extendedByteArray1 = new byte[byteArray.Length + 1]; extendedByteArray1[0] = 0x00; for (int i = 0; i < byteArray.Length; i++) { extendedByteArray1[i + 1] = byteArray[i]; } stopWatch.Stop(); Console.WriteLine(string.Format("#1: {0} ms", stopWatch.ElapsedMilliseconds)); stopWatch.Reset(); //#2 Using a new array and Array.Copy stopWatch.Start(); byte[] extendedByteArray2 = new byte[byteArray.Length + 1]; extendedByteArray2[0] = 0x00; Array.Copy(byteArray, 0, extendedByteArray2, 1, byteArray.Length); stopWatch.Stop(); Console.WriteLine(string.Format("#2: {0} ms", stopWatch.ElapsedMilliseconds)); stopWatch.Reset(); //#3 Using a List stopWatch.Start(); List<byte> byteList = new List<byte>(); byteList.AddRange(byteArray); byteList.Insert(0, 0x00); byte[] extendedByteArray3 = byteList.ToArray(); stopWatch.Stop(); Console.WriteLine(string.Format("#3: {0} ms", stopWatch.ElapsedMilliseconds)); stopWatch.Reset(); Console.ReadLine(); 

And the results are:

#1: 9 ms #2: 1 ms #3: 6 ms 

I've run it multiple times and I got different numbers, but the proportion is always the same: #2 is always the most efficient choice.

My conclusion: arrays are more efficient then Lists (although they provide less functionality), and somehow Array.Copy is really optmized (would like to understand that, though).

Any feedback will be appreciated.

Best regards.

PS: this is not a swordfight post, we are at a Q&A site to learn and teach. And learn.

4 Comments

+1 for "this is not a swordfight post, we are at a Q&A site to learn and teach. And learn."
Thanks. I felt like guys here (myself included!) were getting to emotional =)
Array.Copy will usually be faster because it can copy much larger chunks of memory (32-, 64-, or 128-bits, depending on processor type) at one time than the for loop in test #1. It may even be possible that parts of the copy are done in parallel. I would bet that the gap would narrow between tests #1 and #2 if using int[] or long[] instead of byte[].
Memory copy is a CPU command (movl movsl). Since arrays are laid out together, moving memory between arrays is very fast, since the CPU can do it in a single command.
22

The easiest and cleanest way for .NET 4.7.1 and above is to use the side-effect free Prepend().

Adds a value to the beginning of the sequence.

Example

// Creating an array of numbers var numbers = new[] { 1, 2, 3 }; // Trying to prepend any value of the same type var results = numbers.Prepend(0); // output is 0, 1, 2, 3 Console.WriteLine(string.Join(", ", results )); 

3 Comments

Very succinct and perfect for my use-case! However, OP did state that "speed is important", and this approach does cause copying - so probably not the best in terms of performance, for which the accepted answer likely wins.
Indeed, I was just sad that with a question titled "Prepend to a C# Array" no one mentioned Prepend yet.
I like this answer, but would recommend making it more explicit as to what's going on as with types, in place vs a new copy, and return values.
16

As you surmised, the fastest way to do this is to create new array of length + 1 and copy all the old values over.

If you are going to be doing this many times, then I suggest using a List<byte> instead of byte[], as the cost of reallocating and copying while growing the underlying storage is amortized more effectively; in the usual case, the underlying vector in the List is grown by a factor of two each time an addition or insertion is made to the List that would exceed its current capacity.

... byte[] newValues = new byte[values.Length + 1]; newValues[0] = 0x00; // set the prepended value Array.Copy(values, 0, newValues, 1, values.Length); // copy the old values 

Comments

3

When I need to append data frequently but also want O(1) random access to individual elements, I'll use an array that is over allocated by some amount of padding for quickly adding new values. This means you need to store the actual content length in another variable, as the array.length will indicate the length + the padding. A new value gets appended by using one slot of the padding, no allocation & copy are necessary until you run out of padding. In effect, allocation is amortized over several append operations. There are speed space trade offs, as if you have many of these data structures you could have a fair amount of padding in use at any one time in the program.

This same technique can be used in prepending. Just as with appending, you can introduce an interface or abstraction between the users and the implementation: you can have several slots of padding so that new memory allocation is only necessary occasionally. As some above suggested, you can also implement a prepending interface with an appending data structure that reverses the indexes.

I'd package the data structure as an implementation of some generic collection interface, so that the interface appears fairly normal to the user (such as an array list or something).

(Also, if removal is supported, it's probably useful to clear elements as soon as they are removed to help reduce gc load.)

The main point is to consider the implementation and the interface separately, as decoupling them gives you the flexibility to choose varied implementations or to hide implementation details using a minimal interface.

There are many other data structures you could use depending on the applicability to your domain. Ropes or Gap Buffer; see What is best data structure suitable to implement editor like notepad?; Trie's do some useful things, too.

Comments

3

I know this is a VERY old post but I actually like using lambda. Sure my code may NOT be the most efficient way but its readable and in one line. I use a combination of .Concat and ArraySegment.

 string[] originalStringArray = new string[] { "1", "2", "3", "5", "6" }; int firstElementZero = 0; int insertAtPositionZeroBased = 3; string stringToPrepend = "0"; string stringToInsert = "FOUR"; // Deliberate !!! originalStringArray = new string[] { stringToPrepend } .Concat(originalStringArray).ToArray(); insertAtPositionZeroBased += 1; // BECAUSE we prepended !! originalStringArray = new ArraySegment<string>(originalStringArray, firstElementZero, insertAtPositionZeroBased) .Concat(new string[] { stringToInsert }) .Concat(new ArraySegment<string>(originalStringArray, insertAtPositionZeroBased, originalStringArray.Length - insertAtPositionZeroBased)).ToArray(); 

Comments

2

The best choice depends on what you're going to be doing with this collection later on down the line. If that's the only length-changing edit that will ever be made, then your best bet is to create a new array with one additional slot and use Array.Copy() to do the rest. No need to initialize the first value, since new C# arrays are always zeroed out:

byte[] PrependWithZero(byte[] input) { var newArray = new byte[input.Length + 1]; Array.Copy(input, 0, newArray, 1, input.Length); return newArray; } 

If there are going to be other length-changing edits that might happen, the most performant option might be to use a List<byte> all along, as long as the additions aren't always to the beginning. (If that's the case, even a linked list might not be an option that you can dismiss out of hand.):

var list = new List<byte>(input); list.Insert(0, 0); 

Comments

1

You can let the compiler take the wheel with the optimisations using the new collection expression and spread element:

byte[] newArray = [0x00, ..oldArray]; 

From glancing at my IL on Release build, it seems that it goes the route of creating a new array with the length of the oldArray + 1, and for-looping adding the other array.
So it's not as efficient as the Array.Copy, however, it's a nice one-liner that could be improved over time and by the compiler based on your configuration.

Apparently, the spread element takes the GetEnumerator over an applicable CopyTo. Perhaps I'm missing something!

From docs (where target type is an array):

If the element is a spread element then one of the following is used:

  • A member of a well-known interface or type is invoked to copy items from the spread element expression to the initialization instance.
  • An applicable GetEnumerator instance or extension method is invoked on the spread element expression and for each item from the enumerator, the initialization instance indexer is invoked to add the item at the current index. If the enumerator implements IDisposable, then Dispose will be called after enumeration, regardless of exceptions.
  • An applicable CopyTo instance or extension method is invoked on the spread element expression with the initialization instance and int index as arguments.

Comments

0

I am aware this is over 4-year-old accepted post, but for those who this might be relevant Buffer.BlockCopy would be faster.

2 Comments

Is it though? Answers to this question don't really agree
Yes it is. Answers from your link say that in performance critical situations its better to use Buffer.BlockCopy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.