Problem in List<double[,]> - c#

What is wrong with this (in C# 3.0):
List<double> x = new List<double> { 0.0330, -0.6463, 0.1226, -0.3304, 0.4764, -0.4159, 0.4209, -0.4070, -0.2090, -0.2718, -0.2240, -0.1275, -0.0810, 0.0349, -0.5067, 0.0094, -0.4404, -0.1212 };
List<double> y = new List<double> { 0.4807, -3.7070, -4.5582, -11.2126, -0.7733, 3.7269, 2.7672, 8.3333, 4.7023,0,0,0,0,0,0,0,0,0 };
List<double[,]> z = new List<double[,]>{x,y}; // this line
The error produced is:
Error: Argument '1': cannot convert from 'System.Collections.Generic.List<double>' to 'double[*,*]'
Help needed.

var z = new List<List<double>> { x, y };
However if you want to store your two lists in a twodimensional array ([,]) this is your anwser. You will have to convert it manually as shown there:
public static T[,] To2dArray(this List<List<T>> list)
{
if (list.Count == 0 || list[0].Count == 0)
throw new ArgumentException("The list must have non-zero dimensions.");
var result = new T[list.Count, list[0].Count];
for(int i = 0; i < list.Count; i++)
{
for(int j = 0; j < list.Count; j++)
{
if (list[i].Count != list[0].Count)
throw new InvalidOperationException("The list cannot contain elements (lists) of different sizes.");
result[i, j] = list[i][j];
}
}
return result;
}

The collection initializer for List<double[,]> expects elements of type double[,] (which is a two-dimensional array, similar to a matrix), but you're passing it x and y, which are of type List<double>, which means it's trying to add two lists of doubles as the elements of the new list.
If you're trying add coordinates to the list, then you need a structure of some sort to contain them. You could write your own or you could use System.Drawing.PointF.

double[,] defines a multidimensional array but you are specifying two Lists.
From your Initialization it looks like you are looking for something like
List<PointF> list = new List<PointF> { new PointF (0.0330F, 0.4807F), new PointF (-0.6463F, -3.7070F) };

Shouldn't it be:
List<List<double>,List<double>> z = new List<List<double>, List<double>>{x,y};
But I don't think that is really what you're after is it?

Are you after something like this?
List<double> x = new List<double> { 0.0330, -0.6463, 0.1226, -0.3304, 0.4764, -0.4159, 0.4209, -0.4070, -0.2090, -0.2718, -0.2240, -0.1275, -0.0810, 0.0349, -0.5067, 0.0094, -0.4404, -0.1212 };
List<double> y = new List<double> { 0.4807, -3.7070, -4.5582, -11.2126, -0.7733, 3.7269, 2.7672, 8.3333, 4.7023, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
List<double[]> z = x.Select((x1, index) => new double[2] {x1, y[index]} ).ToList();
EDIT: changed my answer to join the lists on the index correctly instead of looking it up.

Related

I want to create an array of scene indexes and use it, when i need. The problem is that i don't know how to create the array itself

I did this
public int[] sceneIndex;
public Text[] texts;
IEnumerator ChoosingModes()
{
string[] modes = new string[] { "Cocks", "Tanks", "Cars" };
sceneIndex = new int[] { };
for (int i = 0; i < 5; i++)
{
int x = Random.Range(0, modes.Length);
texts[i].text = modes[x];
sceneIndex[i] = x + 3;
yield return new WaitForSeconds(0.75f);
}
}
It obviously doesn't work, what to do with my in array named 'sceneIndex'?
When you do sceneIndex = new int[] { };, you're locking the length of the length of sceneIndex to 0. Instead, try either sceneIndex = new int[number or scenes]; (locking the length of sceneIndex to the number of scenes you have) or just doing nothing. Since the array is public, you can set the values in the inspector and you won't have to define it in the code.

C # Compare 2 lists of ints of different size

I currently have 2 lists that I want to compare which will never have equal length.
List<int> data which is of n length
List<int> numbersToSeekFor which is of n length and contains the set of all distinct values in data
List<Color> colorsToAssign whose length is the same as numbersToSeekFor
What I want to achieve, and not been very successful, is to compare all the items in data to each index of numbersToSeekFor. If this condition is true the first index of colorsToAssignwill be added to a list and then the second index and so forth...
A very dumb example of the following would be this method. Were I am assuming that there are 3 elements in numbersToSeekFor. The output list of this method should also be of equal size as data.
public List<Color> Foo(List<int> data, List<int>numbersToSeekFor, List<Color> colorsToAssign)
{
List<Color> colors = new List<Color>();
for (int i = 0; i < data.Count; i++)
{
if(data[i] == numbersToSeekFor[0])
{
colors.Add(colorsToAssign[0]);
}
if(data[i] == numbersToSeekFor[1] )
{
colors.Add(colorsToAssign[1]);
}
if(data[i] == numbersToSeekFor[2])
{
colors.Add(colorsToAssign[2]);
}
}
return colors;
}
What would be the cleanest way to achieve this?
Thank you for your help
Well, you could use a comination of LINQ .Where and .Select methods:
public static List<Color> Foo3(List<int> data, List<int> numbersToSeekFor, List<Color> colorsToAssign)
{
if (data?.Any() != true || numbersToSeekFor?.Any() != true || colorsToAssign?.Count != data.Count)
{
return new List<Color>();
}
List<Color> colors = data
.Select(d => numbersToSeekFor.IndexOf(d))
.Where(i => i > -1 && i < colorsToAssign.Count)
.Select(i => colorsToAssign[i])
.ToList();
return colors;
}
If I understand it correctly, numbersToSeekFor is meant for mapping a number in data to an index in colorsToAssign. So maybe it would be a good idea to convert to to a Dictionary first:
var mapNumberToIndex = new Dictionary<int, int>();
for (var i = 0; i < numbersToSeekFor.Count; i++)
mapNumberToIndex.Add(numbersToSeekFor[i], i);
Then you could simple use
colors.Add(mapNumberToIndex[data[i]]);
in your loop
You could use a dictionary to map values onto colours, and do away with the need to pass in a separate list of all the distinct values:
public static List<Color> AssignColours(List<int> data, List<Color> coloursToAssign)
{
var result = new List<Color>();
var map = new Dictionary<int, Color>();
int n = 0;
foreach (var datum in data)
{
if (!map.TryGetValue(datum, out var colour))
{
// Next line will throw exception if number of distinct numbers
// is greater than length of coloursToAssign.
colour = coloursToAssign[n++];
map[datum] = colour;
}
result.Add(colour);
}
return result;
}
This code assumes that the count of distinct values is <= the length of coloursToAssign, otherwise there will be an exception at the commented line.
Alternatively (and more efficiently if you're calling this several times) you can precalculate the map like so:
public static Dictionary<int, Color> MapColours(List<int> numbersToSeekFor, List<Color> coloursToAssign)
{
var map = new Dictionary<int, Color>();
for (int i = 0; i < numbersToSeekFor.Count; ++i)
map[numbersToSeekFor[i]] = coloursToAssign[i];
return map;
}
and then use it like so:
var map = MapColours(numbersToSeekFor, coloursToAssign);
...
var colourToUse = map[data[someIndex]];

Is there a way to expand a one-dimensional Array into a 2D Array with the original values in the [0] index of the 2D Array in C#?

I have an Array with Category Names, but now i Need to assign a few Counters to each Category.
Is there a way to expand my 1D-Array to a 2D-Array in C#?
Thanks for helping!
Edit:
PerformanceCounterCategory[] categories;
categories = PerformanceCounterCategory.GetCategories();
string[] categoryNames = new string[categories.Length];
string[] categoryNames_en = new string[categories.Length];
for (int objX = 0; objX < categories.Length; objX++)
{
categoryNames[objX] = categories[objX].CategoryName;
}
Array.Sort(categoryNames);
for (int objX = 0; objX < categories.Length; objX++)
{
Console.WriteLine("{0,4} - {1}", objX + 1, categoryNames[objX]);
}
I have the Array categoryNames with all the Names of the Categories, but in every Category there are a few Counters which i want to assign to their Category somehow...
Unfortunately you can't use Array.Copy since the source and destination array do not have the same dimensions.
Furthermore, you can't expand arrays in C#, since they are initialized with a fixed size.
What you can do is create a new array with a second dimonesion and copy the values over and set the second dimension to a default value.
void Main()
{
int[] sourceCollection = new [] {1,2,3,4,5,6,7} ;
var result = CopyArrayValues(sourceCollection, 2);
result.Dump();
}
//create a new 2d array
T[,] CopyArrayValues<T>(T[] DataSource, int SecondLength)
{
//Initialize the new array
var Target = new T[DataSource.Length, SecondLength];
//Copy values over
for (int i = 0; i < DataSource.Length; i++)
{
Target[i, 0] = DataSource[i];
}
return Target;
}
Output:
If it's ok for you to have array of arrays, you can do something along this pattern:
int[] sourceCollection = new[] { 1, 2, 3, 4, 5, 6, 7 };
int[][] arr = sourceCollection.Select(i => Enumerable.Range(i, 4).ToArray()).ToArray();

Extract integers from 2D Arraylist whose sum is between a range

I'm writing code for a .NETMF application and need to create a function which accepts 2 params int min, int max and returns an array of integers returnedArr from a generated 2D Arraylist arr were the sum of integers inside returnedArr will be between min and max and also I will not know what the size or contents of arr will be prior to calling the method. Only 1 integer per Arraylist inside arr will be selected.
public ArrayList GetNums(int min, int max)
{
//arr will be structured like this
//var arr = new ArrayList
//{
// new ArrayList {10, 34, 56, 60},
// new ArrayList {3, 23, 56, 78, 65, 42},
// new ArrayList {53, 56, 76}
//};
var returnedArr = new ArrayList();
var arr = GenerateArraylistValues();
//solution code here...
return returnedArr;
}
var returnedArr = new ArrayList();
var arr = GenerateArraylistValues();
//solution code here...
return returnedArr;
}
A sample would be GetNums(130,140);
Return arraylist could be Arraylist{56,23,53}
Also bear in mind that I'm confined to using Arraylists so I can't use generic lists, I was thinking that some sort of foreach loop would do the job but can't get my head around how this would work since I no idea what the size of arr will be before hand
-----------SAMPLE 'arr' VALUES---------
var arr = new ArrayList
{
new ArrayList { 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,55,56,59,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,90,93,96,99,102},
new ArrayList { 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,55,56,59,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,90,93,96,99,102},
new ArrayList { 39,40,41,42,43,44,45,46,47,48,49,53,54,55,59,60,61,77,78,79,80,81,82,83,84,85,86,87,88,89,91,92,94,95,97,98,100,101,115,117,118,119,120,121,122,123,124,125,126,127,129,132,135,138,141},
new ArrayList { 60,100,140,180},
new ArrayList { 41,43,45,55,81,83,85,95,121,123,125,135},
new ArrayList { 39,40,41,42,43,44,45,46,47,48,49,53,54,55,59,60,61,77,78,79,80,81,82,83,84,85,86,87,88,89,91,92,94,95,97,98,100,101,115,117,118,119,120,121,122,123,124,125,126,127,129,132,135,138,141},
new ArrayList { 3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,57,63}
};
If the 'arr' is not huge, using recursion and brute force:
public ArrayList GetNums(int min, int max, ArrayList arr)
{
var results = new ArrayList();
//nothing in the arr?
if (arr.Count == 0)
return results;
//arr has only one list inside
if(arr.Count == 1)
{
foreach(int a in (ArrayList)arr[0])
{
if(a >= min && a <= max)
{
var r = new ArrayList();
r.Add(a);
results.Add(r);
}
}
return results;
}
//arr has two or more lists inside
ArrayList firstList = (ArrayList)arr[0];
ArrayList remainingArr = new ArrayList();
for(int i = 1; i < arr.Count; i++)
{
remainingArr.Add(arr[i]);
}
foreach (int a in firstList)
{
var tempResults = GetNums(min - a, max - a, remainingArr);
foreach(ArrayList result in tempResults)
{
var newResult = new ArrayList();
newResult.Add(a);
newResult.AddRange(result);
results.Add(newResult);
}
}
return results;
}
The result is a list of solutions. First valid solution for your example arr is {10, 65, 56}
If it is acceptable to have the same result, of the minimum values, each and every time, then what you could do is to:
start with the smallest value of each sub-array,
sort the remaining values, tracking their source sub-array,
and move up the sorted values until you've met or exceeded the specified min
An example of such functionality (using LINQ for brevity, and converting back to ArrayList) would be as such:
public static ArrayList GetNums(int min, int max)
{
var arr = GenerateArraylistValues();
// Initialize our results with the minimum values from each array.
var results = arr.Cast<ArrayList>().Select(sub => sub.Cast<int>().Min()).ToList();
var others = new List<UnionItem>();
for (int i = 0; i < arr.Count; i++)
{
others = new List<UnionItem>(others
// Concatenate the arrays together.
.Union(((ArrayList)arr[i]).Cast<int>()
// Don't need the min value, which we will start at already. (Optional)
.Where(val => val != results[i])
// Create the UnionItem, to hold the value and the original array source.
.Select(val => new UnionItem(val, i))));
}
// Order our combined values.
others = new List<UnionItem>(others.OrderBy(val => val.Value));
using (var next = others.GetEnumerator())
{
// Progress through the combined values until we (a) meet or exceed min, or (b) run out of values.
while ((results.Sum() < min) && (next.MoveNext()))
{
// Update the list of result values according to the UnionItem source.
results[next.Current.Source] = next.Current.Value;
}
}
// Once through our calculation, check now if we've successfully met the conditions.
int sum = results.Sum();
if (sum >= min && sum <= max)
{
return new ArrayList(results);
}
else
{
// Whatever happens if no valid match.
return new ArrayList();
}
}
private class UnionItem
{
public readonly int Value; // Holds the value from the array.
public readonly int Source; // Holds the index of the source array.
public UnionItem(int value, int source)
{
Value = value;
Source = source;
}
}
I've created the UnionItem class, simply so we can do the tracking of the source array for each value, to substitute back correctly our results.

Initializing jagged arrays

I want to create array 10 * 10 * 10 in C# like int[][][] (not int[,,]).
I can write code:
int[][][] count = new int[10][][];
for (int i = 0; i < 10; i++)
{
count[i] = new int[10][];
for (int j = 0; j < 10; j++)
count[i][j] = new int[10];
}
but I am looking for a more beautiful way for it. May be something like that:
int[][][] count = new int[10][10][10];
int[][][] my3DArray = CreateJaggedArray<int[][][]>(1, 2, 3);
using
static T CreateJaggedArray<T>(params int[] lengths)
{
return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
}
static object InitializeJaggedArray(Type type, int index, int[] lengths)
{
Array array = Array.CreateInstance(type, lengths[index]);
Type elementType = type.GetElementType();
if (elementType != null)
{
for (int i = 0; i < lengths[index]; i++)
{
array.SetValue(
InitializeJaggedArray(elementType, index + 1, lengths), i);
}
}
return array;
}
You could try this:
int[][][] data =
{
new[]
{
new[] {1,2,3}
},
new[]
{
new[] {1,2,3}
}
};
Or with no explicit values:
int[][][] data =
{
new[]
{
Enumerable.Range(1, 100).ToArray()
},
new[]
{
Enumerable.Range(2, 100).ToArray()
}
};
There is no built in way to create an array and create all elements in it, so it's not going to be even close to how simple you would want it to be. It's going to be as much work as it really is.
You can make a method for creating an array and all objects in it:
public static T[] CreateArray<T>(int cnt, Func<T> itemCreator) {
T[] result = new T[cnt];
for (int i = 0; i < result.Length; i++) {
result[i] = itemCreator();
}
return result;
}
Then you can use that to create a three level jagged array:
int[][][] count = CreateArray<int[][]>(10, () => CreateArray<int[]>(10, () => new int[10]));
With a little help from Linq
int[][][] count = new int[10].Select(x => new int[10].Select(x => new int[10]).ToArray()).ToArray();
It sure isn't pretty and probably not fast but it's a one-liner.
There is no 'more elegant' way than writing the 2 for-loops. That is why they are called 'jagged', the sizes of each sub-array can vary.
But that leaves the question: why not use the [,,] version?
int[][][] count = Array.ConvertAll(new bool[10], x =>
Array.ConvertAll(new bool[10], y => new int[10]));
A three dimensional array sounds like a good case for creating your own Class. Being object oriented can be beautiful.
You could use a dataset with identical datatables. That could behave like a 3D object (xyz = row, column, table)... But you're going to end up with something big no matter what you do; you still have to account for 1000 items.
Why don't you try this?
int[,,] count = new int[10, 10, 10]; // Multi-dimentional array.
Any problem you see with this kind of representation??

Categories

Resources