Understanding multidimensional array - c#

I am trying to understand the multidimensional array. I can't find a proper article to understand what the each block denotes to.
for 1D, we know that int[] = single row of elements
for 2D, int[,] = the first index denotes total rows and the second one denotes total columns
for 3D, int[,,] = I read from quora, that first index is row, second is col and the third one can be denoted to a page. So x pages with r rows and c columns. So if x is 2, r is 2 and c is 2, then there will be a total of 2 square matrices if I am correct.
for 4D, int[,,,] = He said, a row, column and a row of page of elements (visualise it as a row of cubes) which I cannot understand and there is no answer for 5D and beyond.
Quora answer link: https://qr.ae/pvKcLb
Next I found this article https://www.mathworks.com/matlabcentral/answers/250488-how-a-4d-and-5d-matrix-or-array-look-like-can-we-say-that-a-4d-array-is-another-for-of-3d-or-reshap#answer_197039 which says as below
A vector is an array of scalars.
A 2D matrix is an array of vectors.
A 3D array is an array of 2D matrices.
A 4D array is an array of 3D arrays.
A 5D array is an array of 4D arrays.
Etc.
So, since his answer looked quiet understandable, I tried coding instead of visualizing and I ended up with the below snippet!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PracticeCSharp.CSharp
{
class CSL10
{
public void MultiDArrExample()
{
int[] _1D = new int[] { 1, 2, 3, 4, 5 };
int[,] _2D = new int[,]
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
int[,,] _3D = new int[,,]
{
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
},
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
}
};
int[,,,] _4D = new int[,,,]
{
{
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
},
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
}
},
{
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
},
{
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
}
}
};
//My head started spinning.. and cant go further..
}
}
}
Can you help to understand this multidimensional array? and what are some real world use cases and what are the alternatives for this multi-D-arrays?
Thanks in advance!

We live in a 3D world, so anything beyond these 3 dimensions becomes difficult for us humans to visualise and imagine.
But this is no problem for a computer. Which can support an almost endless number of dimensions (depending on memory, processing power, etc.)
However, it does mean that it is impossible to find a "real world" example of a 4/5/21 dimensional array. Because there simply aren't any in our world!
See also this article, which explains a bit more and has some more links:
https://www.preposterousuniverse.com/blog/2009/03/30/why-cant-we-visualize-more-than-three-dimensions/

I was trying to understand what each part of an array indicates in order to understand the multi-dimensional array. I understood it then
I just wanted to understand the way of denoting the different portions of an array. And thanks to Caius Jard I understood how it works and I am able to successfully do an object initialization on the multi-dimensional array. I've done upto 6D and it goes on. I am adding the code to the answer, for any one who might need that to understand how the MultiD-Array works
Here is the object initialization code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PracticeCSharp.CSharp
{
class CSL10
{
public void MultiDArrExample()
{
//1 dimensional
//Line
int[] _1D = new int[] { 5, 5 };
//2 dimensional
//Paragraph
int[,] _2D = new int[,]
{
{5, 5 },
{5, 5 }
};
//3 dimensional
//A page with paragraphs
int[,,] _3D = new int[1, 2, 2]
{
{
{5, 5 },
{5, 5 }
}
};
//3 dimensional
//A book with 2 pages and 2,2 paragraphs in each page
int[,,,] _4D = new int[1, 2, 2, 2]
{
//Book 1
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
}
};
//5 dimensional
//A library with 2 books with 2 pages and 2,2 paragraphs in each page
int[,,,,] _5D = new int[1, 2, 2, 2, 2]
{
//Library
{
//Book 1
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
},
//Book 2
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
}
}
};
//6 dimensional
//A town with 2 libraries with 2 books each with 2 pages in each book and 2,2 paragraphs in each page
int[,,,,,] _6D = new int[1, 2, 2, 2, 2, 2]
{
//town
{
//Library 1
{
//Book 1
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
},
//Book 2
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
}
},
//Library 2
{
//Book 1
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
},
//Book 2
{
//Page 1
{
//Para
{5, 5 },
{5, 5 }
},
//Page 2
{
//Para
{5, 5 },
{5, 5 }
}
}
}
}
};
}
}
}
Then Iterating a 6D array
//Iterating a 6D array
int totalTowns = 1;
int totalLibrariesInEachTown = 2;
int totalBooksInEachLibrary = 2;
int totalPagesInEachBook = 2;
int totalRowsInEachPage = 2;
int totalColsInEachPage = 2;
int count = 1;
for (int town = 0; town < totalTowns; town++)
{
for (int library = 0; library < totalLibrariesInEachTown; library++)
{
for (int book = 0; book < totalBooksInEachLibrary; book++)
{
for (int page = 0; page < totalPagesInEachBook; page++)
{
for (int row = 0; row < totalRowsInEachPage; row++)
{
for (int col = 0; col < totalColsInEachPage; col++)
{
Console.WriteLine($"Count: {count++} Reading array location " +
$"[{town},{library},{book},{page},{row},{col}] = " +
_6D[town, library, book, page, row, col]);
}
}
}
}
}
}

Related

How to sum List<int> values but only by cells in C#?

For example I have this as List<List<int>>:
[2,4,4,2,5]
[1,3,6,3,8]
[0,3,9,0,0]
Should return the sum but only taking cells assuming that the cell count is always the same:
[3, 10, 19, 5, 13]
I am trying to find an easy way to solve this using Linq if it is possible because I am doing this with a lot of for loops and if conditions and I am complicating myself.
Is there a possible way to achieve this using Linq?
Linq approach
List<List<int>> items = new List<List<int>>() {
new List<int> { 2, 4, 4, 2, 5 },
new List<int> { 1, 3, 6, 3, 8 },
new List<int> { 0, 3, 9, 0, 0 } };
List<int> result = Enumerable.Range(0, items.Min(x => x.Count)).Select(x => items.Sum(y => y[x])).ToList();
var xx = new List<List<int>>() {
new List<int>() { 2, 4, 4, 2, 5 },
new List<int>() { 1, 3, 6, 3, 8 },
new List<int>() { 0, 3, 9, 0, 0 },
};
var y = xx.Aggregate((r, x) => r.Zip(x).Select(p => p.First + p.Second).ToList());
I am doing this with a lot of for loops and if conditions and I am complicating myself.
You can accomplish it by using a single for loop.
Two possible approaches to achieve that are:
Approach 1
Creating an array with a capacity equal to the size of either of the lists in the original list collection
Filling the array with 0s
Looping through all lists in the original list collection, aggregating the sum for each index
Approach 2
Creating a list based on the first list in the original list collection
Looping through all subsequent lists in the original list collection, aggregating the sum for each index
Both approaches benefit from the assumption given in the question post:
[...] assuming that the cell count is always the same
If your original list collection is defined as a List<List<int>>:
List<List<int>> valuesCollection = new()
{
new() { 2, 4, 4, 2, 5 },
new() { 1, 3, 6, 3, 8 },
new() { 0, 3, 9, 0, 0 },
};
, the two approaches may be implemented as follows:
Approach 1
var indexCount = valuesCollection[0].Count;
var sums = new int[indexCount];
Array.Fill(sums, 0);
foreach (var values in valuesCollection)
{
for (var i = 0; i < sums.Length; i++)
{
sums[i] += values[i];
}
}
Approach 2
Note: Uses namespace System.Linq
var sums = valuesCollection[0].ToList();
foreach (var values in valuesCollection.Skip(1))
{
for (var i = 0; i < sums.Count; i++)
{
sums[i] += values[i];
}
}
Using either approach, sums's resulting content will be { 3, 10, 19, 5, 13 }.
Example fiddle here.

Copy part of 3-d array to 2-d array

Let's say I have a multidimensional array:
var arr = new double[2, 5, 5]
{
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 }
},
{
{ 1, 1, 1, 1, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 1, 1, 1, 1 }
},
};
I want to copy 3 by 3 part of that array starting from index [1,1,1] till index [1,3,3] (all 2 values).
What is the most efficient way of doing so ? So far, I do it with a loop:
var arr2 = new int[3, 3];
int x_start = 1;
int y_start = 1;
for (int i = 0; i < arr2.GetLength(0); i++)
{
for (int j = 0; j < arr2.GetLength(1); j++)
{
arr2[i, j] = arr[1, x_start + i, y_start + j];
}
}
But I wonder if there is a more efficient way of doing it ?
poke already made the same point in their comment, but this is essentially the best way of doing this.
That’s the most efficient way to do it. You are using fast loops and only loop over those indexes you are interested in. - poke
You could possibly cache the two GetLength() calls in an integer, but I doubt that'd make any meaningful difference in performance.

How to create single dimensional, two dimensional,three dimensional as well as multi dimensional array using C#?

I am trying to keep all the combinations (5C1, 5C2, 5C3, 5C4, 5C5) of 1,2,3,4,5 into individual array. So I need to create dynamic array using for loop in c#.
Say for example,
Here n = 5 and r = 1 to 5.
if r = 1 then
My array will be single dimensional array, when r = 2 then it will be two dimensional array, when r = 3 then three dimensional, when r = 4 then four dimensional array and it will e continued up to end of 5.
My code is given below
string[] ShipArrayObj;
public frmResult( string[] ShipArray )
{
InitializeComponent();
ShipArrayObj = ShipArray;
}
private void frmResult_Load(object sender, EventArgs e)
{
string[] arr = ShipArrayObj;
int n = ShipArrayObj.Count();
for (int r = 1; r <= n; r++)
{
StoreCombination(arr, n, r);
richTextBox1.Text = richTextBox1.Text + "/";
}
}
void StoreCombination(string[] arr, int n, int r)
{
string[] data = new string[r];
createCombination (arr, data, 0, n - 1, 0, r);
}
private void createCombination(string[] arr, string[] data, int start, int end, int index, int r)
{
if (index == r)
{
int j = 0;
for (j = 0; j < r; j++)
richTextBox1.Text = richTextBox1.Text + data[j].ToString();//Where I want to set array to keep combination values
return;
}
int i = 0;
for (i = start; i <= end && end - i + 1 >= r - index; i++)
{
data[index] = arr[i];
CreateCombination(arr, data, i + 1, end, index + 1, r);
}
}
I am storing all the combination into a Rich Text Box, but want to keep into array. If anybody help me then I will be grateful to you.
If you're used to something like Java then multidimensional arrays are a little different in syntax in C#.
Here's a page describing how to do them in C#. Here's a snippet from said page:
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
If you're interested in different combinations of things with a fixed number of them, something like this should be all you need.
If you're interested in different combinations of things with a dynamic number of them, something like this should be all you need.
(Unless you're trying to optimize performance, it's better to be readable/expressive, generally speaking.)
You may need to consider whether or not order matters (un-ordered set vs. ordered list). I would assume it doesn't from your code (in which case sorting is good to eliminate "duplicates"), but I can't tell for sure.
Here's a good example that's easy to read and modify for variations and isn't so bad for small numbers:
// -1, 0, ..., 5
var choices = Enumerable.Range(-1, 6);
var possibleChoices =
from a in choices
from b in choices
from c in choices
from d in choices
from e in choices
select (IEnumerable<int>)new [] { a, b, c, d, e };
// Remove -1's because they represent not being in the choice.
possibleChoices =
possibleChoices.Select(c => c.Where(d => d >= 0));
// Remove choices that have non-unique digits.
possibleChoices =
possibleChoices.Where(c => c.Distinct().Count() == c.Count());
// Sort the choices to indicate order doesn't matter
possibleChoices =
possibleChoices.Select(c => c.OrderBy(d => d));
// Remove duplicates
possibleChoices =
possibleChoices.Select(c => new
{
Key = string.Join(",", c),
Choice = c
}).
GroupBy(c => c.Key).
Select(g => g.FirstOrDefault().Choice);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
Output:
0
1
2
3
4
0, 1
0, 2
0, 3
0, 4
1, 2
1, 3
1, 4
2, 3
2, 4
3, 4
0, 1, 2
0, 1, 3
0, 1, 4
0, 2, 3
0, 2, 4
0, 3, 4
1, 2, 3
1, 2, 4
1, 3, 4
2, 3, 4
0, 1, 2, 3
0, 1, 2, 4
0, 1, 3, 4
0, 2, 3, 4
1, 2, 3, 4
0, 1, 2, 3, 4
This is probably a little more dense to understand, hard-coded to this specific variation of combination and involves recursion but is a bit more generic/isn't hard-coded to 5 (and took 0.047s on dotnetfiddle.net instead of 0.094s). It's also completely lazy/IEnumerable.
public static void Main()
{
var possibleChoices = Choose(5);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
}
public static IEnumerable<IEnumerable<int>> Choose(int max)
{
var remaining = Enumerable.Range(0, max);
return ChooseRecursive(remaining, Enumerable.Empty<int>());
}
public static IEnumerable<IEnumerable<int>> ChooseRecursive(IEnumerable<int> remaining, IEnumerable<int> chosen)
{
yield return chosen;
foreach (var digit in remaining)
{
var choices = ChooseRecursive(
remaining.Where(d => d > digit),
chosen.Concat(new [] { digit })
);
foreach (var choice in choices)
{
yield return choice;
}
}
}
Output:
0
0, 1
0, 1, 2
0, 1, 2, 3
0, 1, 2, 3, 4
0, 1, 2, 4
0, 1, 3
0, 1, 3, 4
0, 1, 4
0, 2
0, 2, 3
0, 2, 3, 4
0, 2, 4
0, 3
0, 3, 4
0, 4
1
1, 2
1, 2, 3
1, 2, 3, 4
1, 2, 4
1, 3
1, 3, 4
1, 4
2
2, 3
2, 3, 4
2, 4
3
3, 4
4

C# 2D Array - how to print the largest element in each row

I'm raeding MTA 98-361 and there is a task: You are writing a program that uses a two-dimensional array. The array has four rows and five columns. You need to print the largest element in each row of the array.
My code:
static void Main(string[] args)
{
//[x, y] row, col
int[,] grid = new int[4,5] { { 1, 2, 4, 5, 6 }, //how to get largest number of each row
{ 3, 4, 7, 8, 9 },
{ 5, 6, 56, 12, 45 },
{ 7, 8, 45, 12, 78 }};
for (int row = 0; row < grid.GetLength(0); row++)
{
for (int col = 0; col < grid.GetLength(1); col++)
{
Console.Write(grid[row, col] + "\t ");
}
Console.WriteLine();
}
Console.WriteLine("Row1: {0} {1} {2} {3} {4} ", grid[0, 0], grid[0, 1], grid[0, 2], grid[0, 3], grid[0, 4]);
Console.ReadLine();
}
I know that this is my task, and should solve it, but I'm stuck.
Can you give me advice how to accomplish it?
Thanks!
Here's how you do it without spawning threads:
public static void Main()
{
int[,] grid = new int[4,5] { { 1, 2, 4, 5, 6 }, //how to get largest number of each row
{ 3, 4, 7, 8, 9 },
{ 5, 6, 56, 12, 45 },
{ 7, 8, 45, 12, 78 }};
int w=grid.GetLength(0), h=grid.GetLength(1);
Console.WriteLine(string.Join(",",
Enumerable.Range(0,w).Select(i=>Enumerable.Range(0,h).Select(j=>grid[i,j]).Max())));
}
You can see it in action here: https://dotnetfiddle.net/8u08i3

Linq compare 2 lists of arrays

I would like to compare 2 lists of arrays. Let's take for instance this example:
List<int[]> list1 = new List<int[]>() { new int[4] { 1, 2, 3, 4 }, new int[4] { 1, 2, 3, 5 } };
List<int[]> list2 = new List<int[]>() { new int[2] { 1, 2 }, new int[2] { 3, 4 }, new int[2] { 3, 5 } };
I would like to know for each element in list1 to calculate for every element in list 2 how many common elements they have.
Ex. 1,2,3,4 compared with 1,2 will result to 2 matching elements.
1,2,3,4 compared with 3,5 will result to 1 matching element.
This is not duplicated as I don't wish to compare regular lists. I wish to see for each record in list1 how many items from list2 contain how many common items.
List<int[]> list1 = new List<int[]>() { new int[4] { 1, 2, 3, 4 }, new int[4] { 1, 2, 3, 5 } };
List<int[]> list2 = new List<int[]>() { new int[2] { 1, 2 }, new int[2] { 3, 4 }, new int[2] { 3, 5 } };
var results = list1.Select(x => list2.Select(y => y.Intersect(x).Count()).ToList()).ToList();
Result contains following data: [ [ 2, 2, 1 ], [ 2, 1, 2 ] ]
You can use Enumerable.Intersect to find out common items of first found in second list.
var commonList = list1.Intersect(list2);
The intersection of two sets A and B is defined as the set that
contains all the elements of A that also appear in B, but no other
elements
Edit Since you have array as element of list you have to go through each list item.
List<int[]> list1 = new List<int[]>() { new int[4] { 1, 2, 3, 4 }, new int[4] { 1, 2, 3, 5 } };
List<int[]> list2 = new List<int[]>() { new int[2] { 1, 2 }, new int[2] { 3, 4 }, new int[2] { 3, 5 } };
List<int[]> list3 = new List<int[]>();
for (int i = 0; i < list1.Count; i++)
{
list3.Add(list1[i].Intersect(list2[i]).ToArray());
}
You'd do something like this:
var results =
from x in list1.Select((array, index) => new { array, index })
from y in list2.Select((array, index) => new { array, index })
select new
{
list1_index = x.index,
list2_index = y.index,
count = x.array.Intersect(y.array).Count()
};
foreach(var r in results)
{
Console.WriteLine("({0}, {1}) have {2} item(s) in common.", r.list1_index, r.list2_index, r.count);
}
// (0, 0) have 2 item(s) in common.
// (0, 1) have 2 item(s) in common.
// (0, 2) have 1 item(s) in common.
// (1, 0) have 2 item(s) in common.
// (1, 1) have 1 item(s) in common.
// (1, 2) have 2 item(s) in common.
var commons = list1.Select(x => list2.Select(x.Intersect).ToArray()).ToArray();
Console.WriteLine(commons[0][0]); // Commons between list1[0] and list2[0]
Console.WriteLine(commons[0][1]); // Commons between list1[0] and list2[1]
Console.WriteLine(commons[3][0]); // Commons between list1[3] and list2[0]
Console.WriteLine(commons[3][0].Length); // Number of commons between [3] and [0]
Accourding to ur requirement, I think in C# there isnt such inbuild function in list which do exactly what you want but following function return exactly what you required in resultList. Hope this help you.
private List<int> MatchList()
{
List<int[]> list1 = new List<int[]>() { new int[4] { 1, 2, 3, 4 }, new int[4] { 1, 2, 3, 5 } };
List<int[]> list2 = new List<int[]>() { new int[2] { 1, 2 }, new int[2] { 3, 4 }, new int[2] { 3, 5 } };
List<int> resultList = new List<int>();
for (int i = 0; i < list1.Count; i++)
{
for (int j = 0; j < list2.Count; j++)
{
if (i == j)
{
int result = 0;
foreach (int list1Element in list1[i])
{
foreach (int list2Element in list2[j])
{
if (list1Element == list2Element)
{
result +=1;
}
}
}
resultList.Add(result);
}
}
}
return resultList;
}

Categories

Resources