im trying to multiply each element in three different arrays by 2 with a loop but im having trouble. im really new at this so please excuse any obvious mistakes lol im not even sure ive im using the right kind of loop but heres what i have so far:
int[] firstArray = new int[] { 1, 2, 5, 6, 9 };
int[] secondArray = new int[] { 12, 3, 8, 20, 7 };
int[] thirdArray = new int[] { 2, 4, 6, 8, 10, 12 };
foreach(new int [5] in firstArray)
{
int newArray1= firstArray.Length * 2;
Console.WriteLine(newArray1);
}
i want it to print out the first new array as "2, 4, 10, 12, 18" in the console but when i run it, i get the error type and identifier are both required in a foreach statement.
any help would be greatly appreciated!
Do this with Linq
int[] resultFirstArray = firstArray.Select(r=> r * 2).ToArray();
int[] resultSecondArray = secondArray.Select(r=> r * 2).ToArray();
int[] resultThirdArray = thirdArray.Select(r=> r * 2).ToArray();
Or you can use Array.ConvertAll
Array.ConvertAll converts an entire array. It converts all elements in one array to another type.
var resultFirstArray = Array.ConvertAll(firstArray, x => 2 * x);
var resultSecondArray = Array.ConvertAll(secondArray, x => 2 * x);
var resultThirdArray = Array.ConvertAll(thirdArray, x => 2 * x);
If you just want to show the doubled values:
foreach(int value in firstArray)
{
Console.WriteLine(2 * value);
}
If you want to double the values in the array, then:
for(int i = 0 ; i < firstArray.Length ; i++)
{
firstArray[i] *= 2;
}
Then perhaps to show those values:
foreach(int value in firstArray)
{
Console.WriteLine(value);
}
If you want to create a new array with the values doubled:
var doubledArray = Array.ConvertAll(firstArray, x => 2 * x);
And to output those values:
foreach(int value in doubledArray)
{
Console.WriteLine(value);
}
Related
I am tasked to transform an Excel VBA to a web-based application. I am using Web Forms. I am stuck with a long Excel formula but I have converted half of the long formula into C#.
Here is the Excel formula:
IF(AND(D7="u", H7/F7>1), 0, INDEX(Scoring!$O$8:$O$10, SUMPRODUCT(--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10), ROW(INDIRECT("'Scoring'!$M1:$M3"))))
While here is my progress on the C# method. I need help on the ELSE part:
IF (variable = "u" && ((CurrentValue / AcceptedValue) > 1)){
return 0;
ELSE {
// the INDEX clause on the Excel Formula
}
O8 - O10 values are {2, 1, 0}
N8 - N10 values are {1, 1.5, 9999999999}
E28 is 0
I have also got the result of the remainder of the formula piece by piece. I just need guidance on how to put it in C#.
=INDEX(Scoring!$O$8:$O$10, SUMPRODUCT({1,1,1}, {0,0,0}, 1))
The double minus(--) made it return 0/1 instead of true/false. ROW(INDIRECT($M1-$M3)) is equivalent to 1.
I could use some help on transforming the Excel formula into C# code.
Here is some C# code to replicate this part of your formula:
INDEX(Scoring!$O$8:$O$10, SUMPRODUCT(--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10), ROW(INDIRECT("'Scoring'!$M1:$M3")))
In the code I've had to assign the array {1, 1, 1} for ROW(INDIRECT("'Scoring'!$M1:$M3")). There is some ambiguity in your question around the action of SUMPRODUCT. According to support.office.com
Multiplies corresponding components in the given arrays, and returns the sum of those products.
But some of your detail in the question makes me think you are thinking that each array get summed up and then those results get multiplied together. Anyway, check out the comments in the code below to follow the logic:
// inputs
double[] o8o10 = new double[] { 2, 1, 0 }; // Scoring!$O$8:$O$10
double[] n8n10 = new double[] { 1, 1.5, 9999999999 }; // Scoring!$N8:$N10
double e28 = 0; // E28
// entries to SUMPRODUCT
List<int> test1 = new List<int>();
List<int> test2 = new List<int>();
Array.ForEach(n8n10, x => { test1.Add((e28 <= x) ? 0 : 1); });
Array.ForEach(n8n10, x => { test2.Add((e28 >= x) ? 0 : 1); });
// ROW(INDIRECT("'Scoring'!$M1:$M3")) should be an array !
List<int> test3 = new List<int> { 1, 1, 1 };
// evalue SUMPRODUCT
int sumProductResult = 0;
for (var i=0; i<test1.Count; i++)
{
sumProductResult += test1[i] * test2[i] * test3[i];
}
// evalute INDEX
double indexResult = 0;
indexResult = o8o10[sumProductResult];
// output
Console.WriteLine(indexResult);
Console.ReadKey();
The output for me is 2 because that is the 0th element of the o8o10 array. We get 0 for the array index because
=SUMPRODUCT({1, 1, 1}, {0, 0, 0}, {1, 1, 1})
resolves to:
=SUM(1*0*1, 1*0*1, 1*0*1}
Which gives 0.
HTH
ROW(INDIRECT("'Scoring'!$M1:$M3")) actually evaluates to {1; 2; 3} and
--(E28 <= Scoring!$N8:$N10),--(E28 >= Scoring!$N8:$N10) is --(E28 = Scoring!$N8:$N10)
so the SUMPRODUCT formula is just:
(E28 = Scoring!$N8) * 1 + (E28 = Scoring!$N9) * 2 + (E28 = Scoring!$N10) * 3
and in C#:
double[] n8n10 = { 1, 2, 3 }; double e28 = 2;
double sumProduct = n8n10.Select((d, i) d == e28 ? i + 1 : 0).Sum();
But! because Scoring!$O$8:$O$10 is only 3 cells and the SUMPRODUCT can in theory result in more than 3, the actual aim of the INDEX SUMPRODUCT part seems to be something like this:
double[] o8o10 = { 4, 5, 6 }, n8n10 = { 1, 2, 3 };
double e28 = 2, result = o8o10[0]; // INDEX(array, 0) results in array
if (n8n10[1] == e28) result = o8o10[1];
else if (n8n10[2] == e28) result = o8o10[2];
given:
int[] myArray = new int[]{-8, -17, 12, 8, 16, -3, 7, 3};
Find all values in array closest to 0.
Currently using another code found on the site but it only tells me 1 value.
int nearest = myArray.Select(p => new {Value = p, Difference = Math.Abs(p - searchValue)}).OrderBy(p => p.Difference).First().Value;
In the current case both -3 and 3 are closest to 0 but since -3 comes first it only outputs -3.
Is there another way to do this where it finds all values instead of just First()?
Just to add to this. If you want to do this using O(n) complexity without sorting then you can do it this way :
public List<int> GetClosestNumbers(int searchVal)
{
int[] myArray = new int[] { -8, -17, 12, 8, 16, -3, 7, 3 };
int minimumDist = int.MaxValue;
List<int> output = new List<int>();
for (int i = 0; i < myArray.Length; i++)
{
var currentDistance = Math.Abs(myArray[i] - searchVal);
if (currentDistance < minimumDist)
{
minimumDist = currentDistance;
output.Clear();
output.Add(myArray[i]);
}
else if (minimumDist == currentDistance)
{
output.Add(myArray[i]);
}
}
return output;
}
Use a grouping on the lowest absolute value
int[] result = myArray
.OrderBy(i => Math.Abs(i - searchValue))
.GroupBy(i => Math.Abs(i - searchValue))
.First()
.ToArray();
I want to return elements between two variable indexes in a list.
For example, given this list -
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
I want to loop through the list using to variables for index values. Let’s call the index values X and Y.
So if X equals an index value of 0 and Y equals a value of 5, I need to loop through the index 0-5 and return all of the element values. X and Y could later become index values of 5 through 8 for example.
How would I accomplish this?
You can use Enumerable.Skip and Enumerable.Take
var res = list.Skip(noOfElementToSkip).Take(noOfElementsToTake);
To using variable as indexes
var res = list.Skip(x).Take(y-x+1);
Note You need to pass the start element index to Skip and for taking number of elements you need to pass number of element you want in Take parameter minus the start element number, plus one list is zero-based index.
you can use List.GetRange
var result = list.GetRange(X, Y-X+1);
or a simple for loop
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = X; i <= Y; i++)
{
Console.WriteLine(list[i]);
}
or reinventing the wheel the way you want
public static class Extensions
{
public static IEnumerable<T> GetRange<T>(this IList<T> list, int startIndex, int endIndex)
{
for (int i = startIndex; i <= endIndex; i++)
{
yield return list[i];
}
}
}
foreach(var item in list.GetRange(0, 5))
{
Console.WriteLine(item);
}
int x = 0, y = 5;
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (; x < y; x++)
{
Console.WriteLine(list[x]);
}
This would work if X is always smaller than Y.
If you don't know which is bigger add this before the loop:
if (x > y)
{
x = x ^ y;
y = y ^ x;
x = x ^ y;
}
Another alternative:
int X = 0, Y = 5;
Enumerable.Range(X, Y - X + 1)
.Select(index => list[index]);
It should do the trick -
List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int startindex = 1;
int endIndex = 7;
var subList = list.Skip(startindex).Take(endIndex - startindex-1).ToList();
I have three lists which each list represents only 0s and 1s which related to the pixel values of three images.
My question is how can I get the sum (average) of those three lists and represent it in a new list?
here is example of my image1:
List<int> image1 = new List<int>();
int blackColor = 0;
for (int x = 0; x < bmp1.Width; x++)
{
for (int y = 0; y < bmp1.Height; y++)
{
Color color = bmp1.GetPixel(x, y);
if (color.ToArgb() == Color.Black.ToArgb())
{
image1.Add(0);
blackColor++;
}
else
{
image1.Add(1);
}
}
}
Let me makes sure I understand the problem. You have three lists of the same length:
list A: 1, 2, 4, 3
list B: 3, 2, 4, 1
List C: 2, 7, 1, 8
and you wish to get a third list that is the average of each:
List D: 2, 4, 3, 4
Yes?
This is a job for zip join.
var sumOfFirstTwo = list1.Zip(list2, (x, y)=>x + y);
sumOfFirstTwo is now the sequence that is the sum of the first two lists.
var sumOfAllThree = sumOfFirstTwo.Zip(list3, (x, y)=>x + y);
sumOfAllThree is now the sequence that is the sum of all three lists.
var average = sumOfAllThree.Select(x=>x/3).ToList();
Make sense?
This works for an arbitrary number of lists
var firstList = new[] { 1, 2, 3, 1 };
var secondList = new[] { 2, 3, 1, 1 };
var thirdList = new[] { 3, 1, 2, 2 };
var lists = new[] { firstList, secondList, thirdList };
var listLengths = lists.Select(x => x.Count());
if (listLengths.Distinct().Count() != 1)
throw new Exception("Line lengths must be the same");
var lengthOfEachList = listLengths.First();
var averages = new List<double>();
for (var i = 0; i != lengthOfEachList; ++i) {
averages.Add(lists.Average(x => x[i]));
}
The LINQ way would be
var averages = Enumerable.Range(0, lengthOfEachList).Select(x => lists.Average(y => y[x]));
I have multiple input arrays of Float all of equal size and a single dimension. I want to create a single output Array that contains the average of all the input arrays.
e.g.
//input arrays
float[] array1 = new float[] { 1, 1, 1, 1 };
float[] array2 = new float[] { 2, 2, 2, 2 };
float[] array3 = new float[] { 3, 3, 3, 3 };
float[] array4 = new float[] { 4, 4, 4, 4 };
//the output should be
float[2.5, 2.5, 2.5, 2.5]
I would also like to calculate the standard deviation of the input arrays to.
What is the fastest approach to do this task?
Thanks in advance.
Pete
LINQ to the rescue
This anwer details how to use LINQ to achieve the goal, with maximum reusability and versatility as the major objective.
Take 1 (package LINQ into a method for convenience)
Take this method:
float[] ArrayAverage(params float[][] arrays)
{
// If you want to check that all arrays are the same size, something
// like this is convenient:
// var arrayLength = arrays.Select(a => a.Length).Distinct().Single();
return Enumerable.Range(0, arrays[0].Length)
.Select(i => arrays.Select(a => a.Skip(i).First()).Average())
.ToArray();
}
It works by taking the range [0..arrays.Length-1] and for each number i in the range it calculates the average of the ith element of each array. It can be used very conveniently:
float[] array1 = new float[] { 1, 1, 1, 1 };
float[] array2 = new float[] { 2, 2, 2, 2 };
float[] array3 = new float[] { 3, 3, 3, 3 };
float[] array4 = new float[] { 4, 4, 4, 4 };
var averages = ArrayAverage(array1, array2, array3, array4);
This can already be used on any number of arrays without modification. But you can go one more step and do something more general.
Take 2 (generalizing for any aggregate function)
float[] ArrayAggregate(Func<IEnumerable<float>, float> aggregate, params float[][] arrays)
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => aggregate(arrays.Select(a => a.Skip(i).First())))
.ToArray();
}
This can be used to calculate any aggregate function:
var output = ArrayAggregate(Enumerable.Average, array1, array2, array3, array4);
Instead of Enumerable.Average you can substitute any method, extension method, or anonymous function -- which is useful, as there's no built-in standard deviation aggregate function and also this way the ArrayAggregate function is very versatile. But we can still do better.
Take 3 (generalizing for any aggregate function and any type of array)
We can also make a generic version that works with any built-in type:
T[] ArrayAggregate<T>(Func<IEnumerable<T>, T> aggregate, params T[][] arrays)
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => aggregate(arrays.Select(a => a.Skip(i).First())))
.ToArray();
}
As you can probably tell, this is not the fastest code to do the job. If your program spends all day calculating averages, use something more close to the metal. However, if you want reusability and versatility I don't think you can do much better than the above.
The fastest way in terms of performance, unless you'd like to unroll the for loop is
float[] sums = new float[4];
for(int i = 0; i < 4; i++)
{
sums[i] = (array1[i]+ array2[i] + array3[i] + array4[i])/4;
}
static void Main()
{
float[] array1 = new float[] { 1, 1, 1, 1 };
float[] array2 = new float[] { 2, 2, 2, 2 };
float[] array3 = new float[] { 3, 3, 3, 3 };
float[] array4 = new float[] { 4, 4, 4, 4 };
float[] avg = CrossAverage (array1, array2, array3, array4);
Console.WriteLine (string.Join ("|", avg.Select(f => f.ToString ()).ToArray()));
}
private static float[] CrossAverage (params float [][] arrays)
{
int [] count = new int [arrays[0].Length];
float [] sum = new float [arrays[0].Length];
for (int j = 0; j < arrays.Length; j++)
{
for (int i = 0; i < count.Length; i++)
{
count[i] ++;
sum[i] += arrays[j][i];
}
}
float [] avg = new float [arrays[0].Length];
for (int i = 0; i < count.Length; i++)
{
avg[i] = sum[i] / count[i];
}
return avg;
}
Don't forget bounds checking and divide by 0 checking.
And for the standard deviation after calculating the averages (into the sums array):
// std dev
float[] stddevs = new float[4];
for (int i = 0; i < 4; i++)
{
stddevs[i] += (array1[i] - sums[i]) * (array1[i] - sums[i]);
stddevs[i] += (array2[i] - sums[i]) * (array2[i] - sums[i]);
stddevs[i] += (array3[i] - sums[i]) * (array3[i] - sums[i]);
stddevs[i] += (array4[i] - sums[i]) * (array4[i] - sums[i]);
}
for (int i = 0; i < 4; i++)
stddevs[i] = (float)Math.Sqrt(stddevs[i]/4);
In general, accessing the array directly rather than using LINQ will be a performance win due to allowing the compiler/JIT to optimize. At the very least, array bounds checks can be eliminated and the overhead of using an enumerator will be avoided.