I like to create an int[] with length X and value it with [0,1,2....X]
e.g.
public int[] CreateAA(int X){}
int[] AA = CreateAA(9) => [0,1,2,3,4,5,6,7,8,9]
is there any easy method? Or have to loop and init value
You can avail the functionality of IEnumerable.
int[] arr = Enumerable.Range(0, X+1).ToArray();
This will create a IEnumerable List for you and .ToArray() will satisfy your int array need.
So for X=9 in your case it would generate the array for [0,1,2,3,4,5,6,7,8,9] (as you need)
Using Enumerable.Range(0, 10).ToArray() is very concise but if you want to create a very large array the ToArray extension method will have to collect the numbers into a buffer that will have to be reallocated multiple times. On each reallocation the contents of the buffer is copied to the new larger buffer. .NET uses a strategy where the size of the buffer is doubled on each reallocation (and the initial buffer has four items).
So if you want to avoid multiple reallocations of the buffer you need to create the array in advance:
int[] aa = new int[10];
for (var i = 0; i < aa.Length; i += 1)
aa[i] = i;
This is the most efficient way of initializing the array.
However, if you need an array of say 100,000,000 consecutive numbers then you should look at a design where you don't have to keep all the numbers in an array to avoid the impact of the memory requirement. IEnumerable<int> is very useful for this purpose because you don't have to allocate the entire sequence but can produce it while you iterate and that is exactly what Enumerable.Range does. So avoiding the array of consecutive numbers in the first place may be even better than thinking about how to create it.
Why make a function when it is already there.
For this specific example, use
int[] AA = Enumerable.Range(0, 10).ToArray();
where 0 is the starting value and 10 (X + 1) is the length of array
So a general one applicable to all
int[] AA = Enumerable.Range(0, X + 1).ToArray();
with function and loop:
static int[] f(int X)
{
int[] a = new int[X+1];
for(int i = 0; i < a.Length; i++)
a[i] = i;
return a;
}
To initialize try this
int x = 10;
Enumerable.Range(0, x)
.Select((v, i) => v + i).ToArray();
For completeness, here is a function that creates an array.
I made it a bit more versatile by having parameters for the min and max value, i.e. CreateArray(0, 9) returns {0,1,2,3,4,5,6,7,8,9}.
static int[] CreateArray(int min, int max) {
int[] a = new int[max - min + 1];
for (int i = 0; i < a.Length; i++) {
a[i] = min + i;
}
return a;
}
Related
i want to get the length of a number. i know i can do it with a while loop and dividing by 10 until the number reaches 0 but that takes around 10 line of code and i'm thinking it would be much quicker and much much more efficient to do it this way.
using System;
int[] array = new int[5]{1,12,123,1234,12345};
int[] length = new int[array.Length];
int i = 0;
while (i < 0)
{
length[i] = int.Parse(((array[i]).ToString()).Length);
i++;
}
i = 0;
while (i < array.Length)
{
Console.Write("{0} ", length);
i++;
}
for some reason when i tell it to print the code length of each number instead of printing the length(1 ,2 ,3 ,4 ,5) in just prints system.int32[] 5 times
You don't have to parse .Length since Length return int; your code amended:
int[] array = new int[] {1, 12, 123, 1234, 12345};
//TODO: you may want to put a better name here, say, digitCount
// see comments below
int[] length = new int[array.Length];
for (int i = 0; i < array.Length; ++i)
length[i] = array[i].ToString().Length;
for (int i = 0; i < length.Length; ++i)
Console.Write("{0} ", length[i]);
You can query array with a help of Linq:
using System.Linq;
...
int[] array = new int[] {1, 12, 123, 1234, 12345};
int[] length = array
.Select(item => item.ToString().Length)
.ToArray();
And print length in one go with a help of Join:
Console.Write(string.Join(" ", length));
This is because length is an array, and not the actual item (which I guess you want to print). The fix is easy, replace Console.Write("{0} ", length); with Console.Write("{0} ", length[i]);
Here a few tips for your code:
I see you are using while loops to iterate over something everywhere, so let me teach you a little about another type of loop, the for loop. The for is usually used to do something x amount of times and is constructed like so:
for (int i = 0; i < length.Length; i++)
This might seem complicated but it's actually quite simple, let me explain. We can break down the for loop into 3 sections. The iterator declaration, the iterating condition, and the increment. int i = 0 is the iterator declaration, here we declare and define a variable named i which is an int with the value 0. In the next block (i < length) we declare the condition, when this condition is true we keep on going, when it is false we stop looping. And lastly is the increment or step (i++), this gets executed after every loop and increments the iterator (i in this case) by 1. Rewriting your code with for loops results in this:
int[] array = new int[] {1, 12, 123, 1234, 12345};
int[] length = new int[array.Length];
for (int i = 0; i < array.Length; i++)
{
length[i] = int.Parse(((array[i]).ToString()).Length);
}
for (int i = 0; i < length.Length; i++)
{
Console.WriteLine("{0} ", length[i]);
}
This can still further be improved, for example, currently we are iterating twice over what is essentially the same data, which means we are wasting time. And also, since arrays are enumerable in C#, we can use a foreach loop. This is another type of loop which is almost the same as the for loop, but instead of doing something x amount of times we use to to something with every element of an enumerable. Using it we can do this:
int[] array = new int[] {1, 12, 123, 1234, 12345};
foreach (int element in array)
{
Console.WriteLine($"{element.ToString().Length} ");
}
I also used something called string interpolation(the $ before the ")
This question already has answers here:
How do I check if my array has repeated values inside it?
(8 answers)
Closed 5 years ago.
I would like to check the array I passed in the shuffle method for any duplicates.
I would like to also generate a random number that is the size of a.length.
The thing is that I can't figure out how to check if the array has duplicates and if it does it would generate another number until it is unique from the rest.
public int[] Shuffle(int[] a)
{
//check if the array has duplicates
for (int i = 0; i < a.Length; i++)
{
int curValue = random.Next(a.Length);
if(a.Contains(curValue))
{
curValue = random.Next(a.Length);
}
else
{
a[i] = curValue;
}
}
for (int i = 0; i < a.Length; i++)
{
int r = random.Next(a.Length);
int t = a[r];
a[r] = a[i];
a[i] = t;
}
return a;
}
Can anyone help me?
Here is a function that does what you ask as I presume. Include using System.Linq to run it. I went on the basis of your text, because the code did not make your question clear to me. If you meant something differently please clarify.
static int[] Shuffle(int[] a)
{
Random rnd = new Random();
//Remove duplicates from array
int[] distinct = a.Distinct().ToArray();
//Add the same amount of unique numbers that have been removed as duplicates
int len = a.Length - distinct.Length;
int[] newNumbers = new int[len];
int i = 0;
while(i < len)
{
newNumbers[i] = rnd.Next(a.Length); //NOTE: here i put in the length of array a, but with an int array this will always resolve in a shuffled array containing all digits from 0 to the length-1 of the array.
if (!distinct.Contains(newNumbers[i]) && !newNumbers.Take(i).Contains(newNumbers[i]))
{
++i;
}
}
//Randomize the array
int[] b = a.OrderBy(x => rnd.Next()).ToArray();
//Concatenate the two arrays and return it (shuffled numbers and new unique numbers)
return distinct.Concat(newNumbers).ToArray();
}
As I said in the note, if you remain with an integer array and only allow adding of new random replacement number lower than the length of the array, you and up with a shuffled array of all numbers from 0 to the array length.
Since a new array for newNumbers is generated, you also need to check if a newly generated number is not in that array.
There are a bunch of answers on how to get a subarray with start and end index or start index and length. But I m looking for a way to get an subarray based on index array.
Here is what I have (which works fine but seems clunky).
//sample arrays (could be unordered)
double[] expiry= { 0.99, 0.9, 0.75, 0.60, 0.5, 0.4, ...};
double[] values = { 0.245, 0.24, 0.235, 0.22, 0.21, 0.20, ... };
//find index of all elements meeting criteria in array expiry
int[] expind = expiry
.Select((b, i) => b == 0.75? i : -1)
.Where(i => i != -1).ToArray();
//create new arrays of appropriate size
double[] newvalues = new double[expind.Length];
//populate new arrays based on index
for (int i = 0; i < expind.Length; i++)
newvalues[i] = values[expind[i]];
//check values
foreach (var item in newvalues)
Console.WriteLine(item);
Is there a more efficient and general way of doing this please?
UPDATE
next attempt (Still not super efficient, but at least loopless):
Array.Sort(expiry, values);
double criteria = 0.75;
int start = Array.IndexOf(expiry, criteria);
int last = Array.LastIndexOf(expiry, criteria);
int length = last - start + 1;
double[] newvalues2 = new double[length];
Array.Copy(values, start, newvalues2, 0, length);
Hi you can find the values in this way using lambda expression:
double[] newVals = values.Where((t, i) => expiry[i] == 0.75).ToArray();
This is a bit more concise. no need to actually put the indexes into an expind array; just use the indices directly with the Where() overload that takes an index:
double[] newpoints = points.Where((p, i) => (expiry[i] == 0.75)).ToArray();
double[] newvalues = values.Where((v, i) => (expiry[i] == 0.75)).ToArray();
See deeper discussion.
Now, if for some reason you already have an array of expind indices, but not the original array of expiry it came from, you can do this:
double[] newpoints = expind.Select(ind => values[ind]).ToArray();
Depending on the circumstances, this might work for you.
private static IEnumerable<double> GetByCondition(List<double> expiry, List<double> value)
{
for(int i = 0; i < expiry.Count; i++)
if(expiry[i] == 0.75)
yield return value[i];
}
Furthermore, I'd put it as a extension method, if frequently used in your arrays/lists.
public static IEnumerable<double> GetValuesByExpiry(
this List<double> self, List<double> values)
{
return GetByCondition(self, values);
}
As #Corak mentioned, the problem might be eliminated all together if you merge those two arrays into a single one consisting of touples. If appropriate in your case, of course. You can probably zip them together.
I was having this discussion with my friend who had this question asked to him in the Interview. The Question goes like this. Write a Function which takes in a byte array(2 dimensional) as input along with an Integer n, The initial assumption is all the elements of M*N byte array is zero and the problem is to fill 'n' Byte array elements with value 1, For instance if M=5 and N=5 and the n value is 10 the Byte array should've 10/25 elements to be 1 and rest of the 15 values to be 0. The values filled should be random and one cell in byte array should be filled only once. I was fascinated to try solving this on my own. I've attached the code I've come up with so far.
public Boolean ByteArrayFiller(int a,int b, int n)
{
int count = n;
int iLocalCount = 0;
byte[,] bArray= new byte[a,b];
for (int i = 0; i <a; i++)
for (int j = 1; j <b; j++)
bArray[i, j] = 0;
Random randa= new Random();
int iRandA = randa.Next(a);
int iRandB = randa.Next(b);
while (iLocalCount < n)
{
if (bArray[iRandA, iRandB] == 0)
{
bArray[iRandA, iRandB] = 1;
iLocalCount++;
}
iRandA = randa.Next(a);
iRandB = randa.Next(b);
continue;
}
//do
//{
// //iRandA = randa.Next(a);
// //iRandB = randa.Next(b);
// bArray[iRandA,iRandB]=1;
// iLocalCount++;
//} while (iLocalCount<=count && bArray[iRandA,iRandB]==0);
return true;
}
The code i wrote is in C# but it's straight forward to understand. It's able to do the purpose of the question( I did some trials runs and results came out correctly) perfectly but I have used Random object in C#(Equivalent to Math.Rand in Java) to fill up the byte array and I keep thinking if Rand returns the same values for a and b. There is a good chance for this to go indefinitely. Is that the purpose of the question? or Does the solution that i came up for this question is good enough!
I am curious to see how experts here solve this problem? I am just looking for new ideas to expand my horizon. Any pointers would be greatly appreciated. Thanks for taking the time to read this post!
A while loop trying random locations until it finds a good one is generally a very bad approach. If n = M*N, then the last one will have a probability of 1/(M*N) of finding a match. If M*N are sufficiently large, this can be extremely inefficient.
If M*N is not too large, I would create a temporary array of M*N size, fill it with the numbers 0 through (M*N)-1, and then permutate it - i.e. you walk through it and swap the current value with that of a random other value.
Then you go to the first n elements in your array and set the appropriate cell. (row = value / columns, col = value % columns).
I would treat the array, logically, as a one-dimensional array. Fill the first n positions with the prescribed value, and then shuffle the array.
Given a byte array, and the number of rows and columns in the array, and assuming that the array is already filled with 0:
int NumElements = NumRows * NumCols;
for (int i = 0; i < NumElementsToFill; ++i)
{
int row = i / NumRows;
int col = i % NumCols;
array[row, col] = 1;
}
// Now shuffle the array
Random rnd = new Random();
for (int i = 0; i < NumElements; ++i)
{
int irow = i / NumRows;
int icol = i % NumCols;
int swapWith = rnd.Next(i+1);
int swapRow = swapWith / NumRows;
int swapCol = swapWith % NumCols;
byte temp = array[irow, icol];
array[irow, icol] = array[swapRow, swapCol];
array[swapRow, swapCol] = temp;
}
The key here is converting the one-dimensional index into row/col values. I used / and %. You could also use Math.DivRem. Or create Action methods that do the get and set for you.
Choose a number, which is larger than both N and M and is prime (or co-prime to both N and M). Let's call this number p.
Loop until you've set x numbers:
Generate a random number less than N*M. Call this number `l`.
Then the next place to put the number will be `p*l%(N*M)`, if that position hasn't been set.
A downside to this approach is that if the array is filling up, you'll have more collisions.
Bascially, you need to choose n unique random numbers from range [0, p) (where p = M * N), and map them to positions of 2-dimensional array.
Naive approaches are 1) generate non-unique numbers with retry 2) fill an array with numbers from 0 to p-1, shuffle it and take first n numbers (takes O(p) time, O(p) memory).
Another approach is to choose them with the following algorithm (O(n2) time, O(n) memory, code in Java):
public Set<Integer> chooseUniqueRandomNumbers(int n, int p) {
Set<Integer> choosen = new TreeSet<Integer>();
Random rnd = new Random();
for (int i = 0; i < n; i++) {
// Generate random number from range [0, p - i)
int c = rnd.nextInt(p - i);
// Adjust it as it was choosen from range [0, p) excluding already choosen numbers
Iterator<Integer> it = choosen.iterator();
while (it.hasNext() && it.next() <= c) c++;
choosen.add(c);
}
return choosen;
}
Mapping of generated numbers to positions of 2-dimensional array is trivial.
I need to iterate over an array of arbitrary rank. This is for both reading and writing, so GetEnumerator will not work.
Array.SetValue(object, int) doesn't work on multidimensional arrays.
Array.SetValue(object, params int[]) would require excessive arithmetic for iterating through the multidimensional space. It would also require dynamic invocation to get around the params part of the signature.
I'm tempted to pin the array and iterate over it with a pointer, but I can't find any documentation that says that multidimensional arrays are guaranteed to be contiguous. If they have padding at the end of a dimension then that won't work. I'd also prefer to avoid unsafe code.
Is there an easy way to sequentially address a multidimensional array using only a single index?
Multidimensional arrays are guaranteed to be contiguous. From ECMA-335:
Array elements shall be laid out within the array object in row-major order (i.e., the elements associated with the rightmost array dimension shall be laid out contiguously from lowest to highest index).
So this works:
int[,,,] array = new int[10, 10, 10, 10];
fixed (int* ptr = array)
{
ptr[10] = 42;
}
int result = array[0, 0, 1, 0]; // == 42
You can use the Rank and GetUpperBound property/method to create an indices array that you can pass to the array's SetValue and GetValue methods:
int[] Indices(Array a, int idx)
{
var indices = new int[a.Rank];
for (var i = 0; i < a.Rank; i++)
{
var div = 1;
for (var j = i + 1; j < a.Rank; j++)
{
div *= a.GetLength(j);
}
indices[i] = a.GetLowerBound(i) + idx / div % a.GetLength(i);
}
return indices;
}
..and use it like so:
for (var i = 0; i < array.Length; i++)
{
var indices = Indices(array, i);
array.SetValue(i, indices);
var val = array.GetValue(indices);
}
Perhaps you could join them all into the a single temporary collection, and just iterate over that.