Мultidimensional Аrrays as an argument for method - c#

I wrote a method, that takes a multidimensional array as a parameter and returns the largest numbers of each:
static double[] FindLargest( double[][] NumsInNums ) {
double[] Larges = new double[] {};
int i = 0;
foreach( double[] Nums in NumsInNums ) {
Larges[i] = Nums.Max();
i++;
}
return Larges;
}
But when i call it:
static void Main(string[] args)
{
double[] nums = FindLargest( {{4, 2, 7, 1}, {20, 70, 40, 90}, {1, 2, 0}} );
foreach(double num in nums) {
Console.WriteLine(num);
}
}
But this error appers:
What is wrong here?

You have two problems. Firstly your array declaration has an invalid syntax. It should be like this:
var nums = FindLargest(
new []
{
new double[] { 4, 2, 7, 1},
new double[] { 20, 70, 40, 90},
new double[] { 1, 2, 0}
});
(I think that was probably OK in your actual code, because you seem to be asking about a different problem; see below!)
Secondly, in your FindLargest() method you are creating your result array, Larges with a size of zero. You need to create it with the correct size to accommodate all the results - in this case, it must be the same size as the NumsInNums array, which you can find via NumInNums.Length:
static double[] FindLargest(double[][] NumsInNums)
{
double[] Larges = new double[NumsInNums.Length];
int i = 0;
foreach (double[] Nums in NumsInNums)
{
Larges[i] = Nums.Max();
i++;
}
return Larges;
}
Just for completeness, I should point out that you can use the Linq Enumerable.Select() to simplify the code like so:
static double[] FindLargest(double[][] NumsInNums)
{
return NumsInNums.Select(array => array.Max()).ToArray();
}
The .Select() takes each element of NumInNums (each element is an array) and then calls Enumerable.Max() for it, then takes all the results and puts them in an array (via the ToArray()).

Related

How to Zip two Lists of different size to create a new list that is same as the size of the longest amongst the original lists?

I have two C# Lists of different sizes e.g.
List<int> list1 = new List<int>{1,2,3,4,5,6,7};
List<int> list2 = new List<int>{4,5,6,7,8,9};
I want to use the linq Zip method to combine these two into a list of tuples that is of the size list1. Here is the resulting list I am looking for
{(1,4), (2,5), (3,6), (4,7), (5,8), (6,9), (7,0)} //this is of type List<(int,int)
Since the last item of list1 does not has a counterpart in list2, I fill up my last item of the resulting list with a default value (in this case 0 as in my case it will never appear in any of the original lists).
Is there a way I can use the linq Zip method alone to achieve this?
You can use Concat to make them both the same size, and then zip it:
var zipped = list1.Concat(Enumerable.Repeat(0,Math.Max(list2.Count-list1.Count,0)))
.Zip(list2.Concat(Enumerable.Repeat(0,Math.Max(list1.Count-list2.Count,0))),
(a,b)=>(a,b));
Or create an extension method:
public static class ZipExtension{
public static IEnumerable<TResult> Zip<TFirst,TSecond,TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst,TSecond,TResult> func,
TFirst padder1,
TSecond padder2)
{
var firstExp = first.Concat(
Enumerable.Repeat(
padder1,
Math.Max(second.Count()-first.Count(),0)
)
);
var secExp = second.Concat(
Enumerable.Repeat(
padder2,
Math.Max(first.Count()-second.Count(),0)
)
);
return firstExp.Zip(secExp, (a,b) => func(a,b));
}
}
So you can use like this:
//last 2 arguments are the padder values for list1 and list2
var zipped = list1.Zip(list2, (a,b) => (a,b), 0, 0);
There is a useful and popular MoreLinq library. Install it and use.
using MoreLinq;
var result = list1.ZipLongest(list2, (x, y) => (x, y));
Try this using Zip function-
static void Main(string[] args)
{
List<int> firstList = new List<int>() { 1, 2, 3, 4, 5, 6, 0, 34, 56, 23 };
List<int> secondList = new List<int>() { 4, 5, 6, 7, 8, 9, 1 };
int a = firstList.Count;
int b = secondList.Count;
for (int k = 0; k < (a - b); k++)
{
if(a>b)
secondList.Add(0);
else
firstList.Add(0);
}
var zipArray = firstList.Zip(secondList, (c, d) => c + " " + d);
foreach(var item in zipArray)
{
Console.WriteLine(item);
}
Console.Read();
}
Or you can try this using ZipLongest Function by installing MoreLinq nuget package-
static void Main(string[] args)
{
List<int> firstList = new List<int>() { 1, 2, 3, 4, 5, 6, 0, 34, 56, 23 };
List<int> secondList = new List<int>() { 4, 5, 6, 7, 8, 9, 1 };
var zipArray = firstList.ZipLongest(secondList, (c, d) => (c,d));
foreach (var item in zipArray)
{
Console.WriteLine(item);
}
Console.Read();
}
Try this code-
static void Main(string[] args)
{
List<int> firstList=new List<int>() { 1, 2, 3, 4, 5, 6,0,34,56,23};
List<int> secondList=new List<int>() { 4, 5, 6, 7, 8, 9,1};
int a = firstList.Count;
int b = secondList.Count;
if (a > b)
{
for(int k=0;k<(a-b);k++)
secondList.Add(0);
}
else
{
for (int k = 0; k < (b-a); k++)
firstList.Add(0);
}
for(int i=0;i<firstList.Count;i++)
{
for(int j=0;j<=secondList.Count;j++)
{
if(i==j)
Console.Write($"({Convert.ToInt32(firstList[i])},{ Convert.ToInt32(secondList[j])})" + "");
}
}
Console.Read();
}

Zero out subarrays if sums don't match

Given two Lists of integer arrays of the form:
genData = { {1,2,3,4}, {1,2,3,4}, {1,2,3,4}, {1,2,3,4}};
orgData = {{1,2,3,4}, {1,2,3,4}, {2,4,6,8}, {1,2,3,4}};
I'd like to determine if the sum of two subarrays at the same index in both lists don't match. If the sums match, do nothing. If the sums don't match, convert every integer in both subarrays into a 0.
For example, in the two lists above the subarrays at index 2 have a non-matching sum (10 vs 20). I'd like to convert the lists to
genData = { {1,2,3,4}, {1,2,3,4}, {0,0,0,0}, {1,2,3,4} };
orgData = { {1,2,3,4}, {1,2,3,4}, {0,0,0,0}, {1,2,3,4} };
I'm trying to first create a list if sums by trying
var genDataSum = genDataList.ForEach(x => x.Sum());
But obviously, that's throwing up errors..."Cannot assign void to an implicitly typed value".
Any help or guidance will be greatly appreciated.
You need to use select to get the sum. list.foreach works like normal for loop.
List<int[]> genData = new List<int[]>
{
new int[] { 1, 2, 3, 4 },
new int[] { 1, 2, 3, 4 },
new int[] { 1, 2, 3, 4 },
new int[] { 1, 2, 3, 4 }
};
List<int[]> orgData = new List<int[]>
{
new int[] { 1, 2, 3, 4 },
new int[] { 1, 2, 3, 4 },
new int[] { 2, 4, 6, 8 },
new int[] { 1, 2, 3, 4 }
};
var sumsGenData = genData.Select(a => a.Sum()).ToList();
var sumsOrgData = orgData.Select(a => a.Sum()).ToList();
for (int i = 0; i < sumsGenData.Count; i++)
{
if (sumsGenData[i] != sumsOrgData[i])
{
orgData[i] = new int[] { 0, 0, 0, 0 };
}
}
ForEach doesn't return anything. Use Select.
var orgData = { {1,2,3,4}, {1,2,3,4}, {0,0,0,0}, {1,2,3,4} };
var sums = orgData.Select( a => a.Sum() );

Creating a method that returns an array

I'm to create a helper method that returns a new array whose elements are the square of an original array. But when I run the code, the console returns "System.Double[]". How can I fix this?
Here's the method code:
static double[] powerOfTwo(int[] arr)
{
double[] elevatedPower = new double[10];
elevatedPower[0] = Math.Pow(arr[0], 2);
elevatedPower[1] = Math.Pow(arr[1], 2);
elevatedPower[2] = Math.Pow(arr[2], 2);
elevatedPower[3] = Math.Pow(arr[3], 2);
elevatedPower[4] = Math.Pow(arr[4], 2);
elevatedPower[5] = Math.Pow(arr[5], 2);
elevatedPower[6] = Math.Pow(arr[6], 2);
elevatedPower[7] = Math.Pow(arr[7], 2);
elevatedPower[8] = Math.Pow(arr[8], 2);
elevatedPower[9] = Math.Pow(arr[9], 2);
return elevatedPower;
}
And the code to print it in the console:
static void Main(string[] args)
{
double[] powerValues = powerOfTwo(new int[] {1,2,3,4,5,6,7,8,9,10});
Console.Write(powerValues);
Console.ReadLine();
}
Your method works fine. But when you do Console.WriteLine(powerValues), the compiler calls ToString() method of the datatype which is System.double[].
foreach(var value in powerValues)
Console.WriteLine(value);
With Linq, using System.Linq;
var powerValues = (new int[] {1,2,3,4,5,6,7,8,9,10}).Select(x => x*x);
Actually, you are not printing your values. You try to print your array which returns it's full type name as System.Double[] since ToString calls it which is called by Console.Write explicitly.
You don't even need such a method. Just use Enumerable.Select to generate IEnumerable<int> which contains squared values like;
var values = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (var value in values.Select(i => i * i))
{
Console.Write(value); // 149162536496481100
}
And I would use Console.WriteLine to writing those values in separate lines each or put at least a white space after them if you choose Write like Console.Write(value + " ")
When you calling Console.Write(powerValues); actually call Console.Write(powerValues.ToString());ToString returns a string that represents the current object. For double[] this is "System.Double[]".
Change your code like this :
static void Main(string[] args)
{
double[] powerValues = powerOfTwo(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
foreach (var value in powerValues)
{
Console.WriteLine(value);
}
Console.ReadLine();
}
Write Your code in just simple one line using below code.
new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }.ToList().ForEach(i => Console.WriteLine(i * i));
and each value are display in new line so result are also good compare to other.

How to access and re-format Jagged Array in C#

I have 2D array in c#, like this:
int[][] 2darray = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
how can I get one column as normal array, like
int[] array = 2darray[1][]; //example, not working
and have
int[] array = {3,4};
?
Thanks.
There are several reasons why your code can't compile
This way it works:
int[][] array2d = { new[]{ 1, 2 }, new[]{ 3, 4 }, new[]{ 5, 6 }, new[]{ 7, 8 } };
int[] array = array2d[0];
Problems:
2darray is not a valid variable name
The indexing is wrong
The initialization of the original array is wrong
EDIT:
As stated by #heltonbiker, if you require all elements of the first column, you can use this:
int[] col = array2d.Select(row => row[0]).ToArray();
For an array with two columns and four rows, you can use LINQ this way:
using System.Linq;
first_column = _2darray.Select(row => row[0]).ToArray();
Note that changing the first or second array will not change the other one.
You are confusing jagged arrays and multidimensional arrays in C#. While they are similar, there is a slight difference. Rows in a jagged array can have a different number of elements, while in a 2D-array they are of the same length. Therefore when working with jagged arrays you need to remember to write handling for a missing column element. I composed a sample console app below to show how both of them work - it uses 0 as a substitute for a missing element, but you can throw an error etc.:
using System.Collections.Generic;
namespace JaggedArrayExample
{
class Program
{
static void Main(string[] args)
{
//jagged array declaration
int[][] array1;
//jagged array declaration and assignment
var array2 = new int[][] {
new int[] { 1, 2 },
new int[] { 3, 4 },
new int[] { 5, 6 },
new int[] { 7, 8 }
};
//2D-array declaration
int[,] array3;
//2D-array declaration and assignment (implicit bounds)
var array4 = new int[,] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//2D-array declaration and assignment (explicit bounds)
var array5 = new int[4, 2] {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
//get rows and columns at index
var r = GetRow(array2, 1); //second row {3,4}
var c = GetColumn(array2, 1); //second column {2,4,6,8}
}
private static int[] GetRow(int[][] array, int index)
{
return array[index]; //retrieving the row is simple
}
private static int[] GetColumn(int[][] array, int index)
{
//but things get more interesting with columns
//especially if jagged arrays are involved
var retValue = new List<int>();
foreach (int[] r in array)
{
int ub = r.GetUpperBound(0);
if (ub >= index) //index within bounds
{
retValue.Add(r[index]);
}
else //index outside of bounds
{
retValue.Add(0); //default value?
//or you can throw an error
}
}
return retValue.ToArray();
}
}
}
try this, it should work
int[] array = array2d[1];
Change the name of the variable to array2d, you cannot have variable that starts with number, a variable can start with letter or underscore.

Converting array/matrix initialization code from C++ to C#

I am in the middle of converting C++ code to C#. I am having trouble with some C++ array static initialization. Consider the following piece of C++:
int Values[][32] = {
{}, {}, {1, 2, 3}, {1}
};
What this does is creates a matrix of 4x32 integers. I need to do same or similar in C# in as straightforward way as possible. I am looking to get either
static int[][] Values = {...};
...or
static int[,] Values = {...};
The thing is C# does not seem to allow array initialization with uneven sub-array sizes. Other than this, if one specifies new int[4,32] {...} then everything between curly braces must be of exactly 32 length. With C++ one can specify {1, 2, 3} and the compiler will fill in the rest of the missing array members with zeros.
[EDIT] I have tried using LINQ and got what I desire but it looks cumbersome.
In C# the size of your array initializer must match the declared size of the array. You do not need to declare the size if you would like to avoid duplication.
If you need all entries to be of the same size, you can do it with a little helper function Expand, like this:
static int[] Expand(int[] src, int size) {
var res = new int[size];
Array.Copy(src, res, src.Length);
return res;
}
static int[][] Values = new int[4][] {
Expand(new[] {1}, 32)
, Expand(new[] {1,2,3}, 32)
, Expand(new[] {1,2,3}, 32)
, Expand(new[] {1,2,3, 4, 5}, 32)
};
I deleted my previous answer and am adding another (less eloquent) one that should work.
// utility function you can put in a class
static int[] BuildArray32(params int[] values)
{
int[] retVal = new int[32];
Array.Copy(values, retVal, values.Length);
return retVal;
}
// array initializer code
int[][] Values = {
BuildArray32(),
BuildArray32(),
BuildArray32(1, 2, 3),
BuildArray32(1),
};
EDIT Or you could make a builder class :)
class MatrixBuilder
{
int width;
List<int[]> rows;
public MatrixBuilder(int width)
{
this.width = width;
this.rows = new List<int[]>();
}
public MatrixBuilder Add(params int[] row)
{
int[] wideRow = new int[width];
Array.Copy(row, wideRow, row.Length);
rows.Add(wideRow);
return this;
}
public int[][] ToMatrix()
{
return rows.ToArray();
}
}
int[][] Values2 = new MatrixBuilder(32)
.Add()
.Add()
.Add(1, 2, 3)
.Add(1)
.ToMatrix();
You can't do it in c#. you can either initialise the arrays all to zeros, then apply your known initial values afterwards:
int[][] initAll = new []
{
new int[32] ,
new int[32] ,
new int[32] ,
new int[32]
};
or initialize a jagged array:
int[][] initJagged = new[]
{
new[] {1, 3, 5, 7, 9},
new[] {1, 3, },
new[] {1, 3,0,0,0,0,},
new int[32]
};

Categories