I have searched in net but not getting exactly what I need.
I have a bitarray of size 15,936. I need to divide this bit array into list of bitarrays , with each bit array having 32 bits(15936/32 = 498 bitarray list).
Not able to find exactly how to divide bitarray. Please do help.
Thanks,
The first that you want 32-bit values makes this pretty easy, because you can copy it to an int[], then create one BitArray per int, passing the data by creating a single-element int array:
int[] values = new int[bigBitArray.Length / 32];
bigBitArray.CopyTo(values, 0);
var smallBitArrays = values.Select(v => new BitArray(new[] { v })).ToList();
Or more efficiently, reusing the same int[] for each iteration:
int[] values = new int[bigBitArray.Length / 32];
bigBitArray.CopyTo(values, 0);
// Reuse this on every iteration, to avoid creating more arrays than we need.
// Somewhat ugly, but more efficient.
int[] buffer = new int[1];
var smallBitArrays = values.Select(v =>
{
buffer[0] = v;
return new BitArray(buffer))
}).ToList();
If those give you the bit arrays in the opposite order to what you expect, just call Array.Reverse(values) after the CopyTo call.
It's a pity that BitArray doesn't have a constructor taking an existing array, offset and count... that would make it significantly more efficient. (As would a "slice copy" operation, of course.)
A more general purpose option would be to create an extension method precisely for that "slice copy" part:
public static BitArray CopySlice(this BitArray source, int offset, int length)
{
// Urgh: no CopyTo which only copies part of the BitArray
BitArray ret = new BitArray(length);
for (int i = 0; i < length; i++)
{
ret[i] = source[offset + i];
}
return ret;
}
Then:
var smallBitArrays = Enumerable
.Range(0, bigBitArray.Length / 32)
.Select(offset => bigBitArray.CopySlice(offset * 32, 32))
.ToList();
You can copy your bit array into an array of bytes, split that array into chunks and create new bit arrays:
const int subArraySizeBits = 32;
const int subArraySizeBytes = subArraySizeBits / 8;
byte[] bitData = new byte[myBitArray.Length / subArraySizeBytes];
myBitArray.CopyTo(bitData, 0);
List<BitArray> result = new List<BitArray>();
for (int index = 0; index < bitData.Length; index += subArraySizeBytes) {
byte[] subData = new byte[subArraySizeBytes];
Array.Copy(bitData, index * subArraySizeBytes, subData, 0, subArraySizeBytes);
result.Add(new BitArray(subData));
}
Related
I have a 8x8x3 array with some values. What I want to do is make a list of just the 1D arrays.
What I've got so far:
int[] packIt(int[,,] data, int factor) {
List<int[]> toReturn = new List<int[]>();
int[] test = data[0, 0];
So unless I'm missing something, I make a list of one dimensional arrays and try to fit in the one dimensional array at data[0, 0] (the test is just a placeholder so far). The error I'm getting is "Wrong number of indices", however if I follow the data[0,0,0] (which gives no error) I'll just get the 1 value at the location. I could do it manually, but am just wondering if there is an implementation for the functionality that I'm trying to do, as I will be using it a lot. Thanks a bunch.
You don't need to do anything specific to turn a 3D array into a 1D one; you can just enumerate it:
foreach(var x in multiDim)
...
This will print 1 to 8:
var x = new int[2,2,2];
x[0,0,0] = 1;
x[0,0,1] = 2;
x[0,1,0] = 3;
x[0,1,1] = 4;
x[1,0,0] = 5;
x[1,0,1] = 6;
x[1,1,0] = 7;
x[1,1,1] = 8;
foreach(int i in x)
Console.WriteLine(i);
To this end you can just straight enumerate your array in chunks of whatever:
var out = new List<int[]>();
var arr = new int[chunkSize];
out.Add(arr);
var idx = 0;
foreach(var x in miltiDimArray){
if(idx == chunkSize){
out.Add(arr = new int[chunkSize]);
idx = 0;
}
arr[idx++] = i;
}
Note that I don't try to make the ticks array smaller if the chunk size doesn't divide into the number of elements. idx will have a residual value you can use to work out what to resize the last array by if that is important
I want to convert decimal integers taken from an array and convert into 4-bit binary and store each of the bit into array in c#
static void Main()
{
BinaryInput a = new BinaryInput();
int[] input = { 7, 0, 0, 0, 2, 0, 4, 4, 0 };
int x;
int[] bits = new int[36];
ArrayList Actor = new ArrayList();
for (int i = 0; i < input.Length; i++)
{
x = (int)input[i];
string result = Convert.ToString(x, 2);
bits = result.PadLeft(4, '0').Select(c =>int.Parse(c.ToString())).ToArray();
Actor.Add(bits);
}
}
The ArrayList Actor consists of 9 arrays and each array consist of binary number......but i want to add each of the binary bit in a single array as an individual element of the array or arraylist {0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0}
You can write a method to get the "bits" of a number like this
private static IEnumerable<int> ToBitSequence(this int num, int size)
{
while (size > 0)
{
yield return num & 1;
size--;
num >>= 1;
}
}
Then you can use it in the following way to get your desired results.
int[] input = { 7, 0, 0, 0, 2, 0, 4, 4, 0 };
var bits = input.Reverse().SelectMany(i => i.ToBitSequence(4)).Reverse();
Console.WriteLine(string.Join(",", bits));
Results in
0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0
The reason for the two Reverse calls is because ToBitSequence will return the least significant bit first, so by feeding the number in reverse order and then reversing the results you will get the bits from most significant to least starting with the first number in your list.
This is preferable to all the parsing and formatting between char, string, and int that you're currently doing.
However if you just change Actor to List<int> and do Actor.AddRange(bits); that would also work.
Use BitArray
BitArray b = new BitArray(new byte[] { x });
int[] bits = b.Cast<bool>().Select(bit => bit ? 1 : 0).ToArray();
This will give you the bits, then use
bits.Take(4).Reverse()
to get the least significant 4 bits in most-significant order first for each number.
I know I can convert a byte array to an int array with the following:
int[] bytesAsInts = yourBytes.Select(x => (int)x).ToArray();
How can I convert a byte array to an int array of a fixed size and pad the remaining with 0x00?
E.g., my byte array is 10 bytes, and I want to create an int array of length 14. The code should convert the 10 bytes of my byte array, and pad the remaining 4 with 0x00
Write yourself a reusable extension method that can pad a sequence:
static IEnumerable<T> AppendPadding(this IEnumerable<T> items, int totalCount, T paddingItem) {
int count = 0;
foreach (var item in items) {
yield return item;
count++;
}
for (int i = count; i < totalCount; i++)
yield return paddingItem;
}
And use it like this:
int[] bytesAsInts = yourBytes.Select(x => (int)x).AppendPadding(14, 0).ToArray();
This works on any kind of sequence with a single linear pass over the sequence. It is also lazy. Abstracting away the problem of padding a sequence allows you remove the complexity of doing the padding from the main algorithm. It is now hidden in some other place nobody has to care about. Factoring out unimportant details leads to clean code because all the complexity is hidden behind a well-defined interface.
int[] array = new int[14];
bytesAsInts.CopyTo(array, 4);
Maybe not most readable, but oneliner :)
int[] bytesAsInts = yourBytes.Select(x => (int)x)
.Concat(Enumerable.Repeat(0,14-yourBytes.Length)).ToArray();
#usr definitely has a great answer. Here's another way, not as robust. But explains the logic, useful for any language, implemented in its own way. Here desiredSize could be set by input.
int desiredSize = 14;
int[] myArray = new int[desiredSize ];
for(int i = 0; i < myArray.Length; i++)
{
if(i <= yourBytes.Length)
myArray[i] = (int)yourBytes[i];
else
myArray[i] = 0x00;
}
The way I get a value from a single dimensional array is:
Random random = new Random();
getit = w[r.Next(0, w.Length)];
Can you please tell me how do I do the same for two dimensional array?
To ensure that you have an even distribution you shouldn't be generating multiple random numbers. Calculate the total possible number of values by multiplying the lengths of the dimensions, choose an index, and then find the one item that corresponds to that index:
public static T GetRandomValue<T>(T[,] array, Random random)
{
int values = array.GetLength(0) * array.GetLength(1);
int index = random.Next(values);
return array[index / array.GetLength(0), index % array.GetLength(0)];
}
Assuming you have a simple two-dimensional array [,]1, not a jagged array [][], then you can use the Array.GetLength method to get the length of each array dimension. For example:
Random random = new Random();
string[,] arr = new string[10, 10];
int i1 = r.Next(0, arr.GetLength(0));
int i2 = r.Next(0, arr.GetLength(1));
string value = arr[i1, i2];
1) It is possible for the lower bound of a multi-dimensional array to be different from the default of 0. In that case, use the Array.GetLowerBound method appropriately.
If you have a jagged array instead [][], not a real two-dimensional array [,], then you can do it sequentially:
Random random = new Random();
string[][] arr = new string[][10];
for (int i = 0; i < arr.Length; i++)
arr[i] = new string[10];
int i1 = r.Next(0, arr.Length);
string[] subarr = arr[i1];
int i2 = r.Next(0, subarr.Length);
string value = subarr[i2];
Not really the fastest method, but you could also do this with a bit of Linq:
var totalSize = Enumerable.Range(0, array.Rank).Aggregate(0, (l, r) => l * array.GetLength(r));
var getit = w.ElementAt(r.Next(0, totalSize));
This works for arrays of any dimension.
To create and initialize an array with another array I currently do this:
void Foo( int[] a )
{
int[] b = new int[ a.Length ];
for ( int i = 0; i < a.Length; ++i )
b[ i ] = a[ i ];
// Other code ...
}
Is there a shorter or more idiomatic way of doing this in C#?
It will be great if this can be done in a single statement, like in C++:
vector<int> b( a );
If this cannot be done in a single statement, I will take what I get :-)
I like using LINQ for this:
int[] b = a.ToArray();
That being said, Array.Copy does have better performance, if this will be used in a tight loop, etc:
int[] b = new int[a.Length];
Array.Copy(a, b, a.Length);
Edit:
It will be great if this can be done in a single statement, like in C++:
vector b( a );
The C# version of this would be:
List<int> b = new List<int>(a);
List<T> is C#'s equivalent to std::vector<T>. The constructor above works with any IEnumerable<T>, including another List<T>, an array (T[]), etc.
Use Array.Copy to copy an array
int[] source = new int[5];
int[] target = new int[5];
Array.Copy(source, target, 5);
Clone() and ToArray() are syntactically nice because you don't need to pre-allocate a destination array, but in terms of performance, Array.Copy() is the fastest method (see caveat below).
The reason for Array.Copy() being so fast is that it doesn't allocate any memory. However, if you require your arrays to be copied to a new region of memory each time, then Array.Copy() is no longer the fastest method.
Here are my performance results:
Copy: 0 ms
Copy (with allocation): 449 ms
Clone: 323 ms
ToArray: 344 ms
And here's the code I used:
const int arrayLength = 100000;
const int numberCopies = 1000;
var a = new int[arrayLength];
var b = new int[arrayLength];
var stopwatch = new Stopwatch();
for (var i = 0; i < numberCopies; i++) {
Array.Copy(a, b, arrayLength);
}
Console.WriteLine($"Copy: {stopwatch.ElapsedMilliseconds} ms");
stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
var c = new int[arrayLength];
Array.Copy(a, c, arrayLength);
}
Console.WriteLine($"Copy (with allocation): {stopwatch.ElapsedMilliseconds} ms");
stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
b = (int[]) a.Clone();
}
Console.WriteLine($"Clone: {stopwatch.ElapsedMilliseconds} ms");
stopwatch.Restart();
for (var i = 0; i < numberCopies; i++) {
b = a.ToArray();
}
Console.WriteLine($"ToArray: {stopwatch.ElapsedMilliseconds} ms");
Also try the default Clone() function which is implemented from the IClonable interface.
int[] b = a.Clone() as int[];
You can achieve this easily by creating new empty array or you can use the given array.
int[] arr = { 1, 2, 0, 3, 4, 5, 0, 6, 0, 7, 8, 9, 0 };
int[] newArray = new int[arr.Length];
Array.Copy(arr, newArray, arr.Length);
foreach (var item in newArray)
{
if(item != 0)
Console.WriteLine(item);
}
This solution is by no way the fastest nor the most elegant, but if you need to either skip some of the elements from the original array, or perhaps transform them you could do this with Linq
var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Select(s => s).ToArray();
// targetArray now contains 1,2,3,4,5,6,7,8,9
Admitted, that looks a bit stupid, unless you need to perform some kind of operation during copying
var sourceArray = new int[] {1,2,3,4,5,6,7,8,9 };
var targetArray = sourceArray.Skip(1).Take(3).Select(s => s*s+4).ToArray();
// targetArray now contains 8,13,20