List of arrays holding 2 objects each - c#

What is the correct way to define a List holding arrays of objects of type T?
Each array holds only 2 objects.
Based on this definition:
working: double[] balance = new double[10];
I tried
not working: List<T[]> arrList = new List<T[2]>();
I need to build a list that looks like
([obj1,obj2] ... [objn,objm] ...)
Thank you
D.

There is no way to use a fixed-size for the arrays in the list. You have to do this:
List<T[]> arrList = new List<T[]>();
and then trust the outside code that each array added to the list will have exactly two items.
The only other options I can think of right now are using tuples:
List< (T,T) > arrList = new List< (T,T) >();
or creating your own class type for the List with an indexer property and exactly two members.

Related

Reach a specific element of an array in a list

I have a list that contains string arrays with 3 elements, I need to get the value of the third element of the array that is in the list but I can't figure out the syntax and I can't find anything online on how to do it. My best guess so far has been something along the lines of:
Console.WriteLine(myList[0], myArray[2]);
So I want to specify what index of the list I want to work with, and then specify the index of the array that I want the value from.
You can do it like this:
public static void Main()
{
var myList = new List<string[]>(){
new string[]{"a-first","a-second","a-third"},
new string[]{"b-first","b-second","b-third"},
new string[]{"c-first","c-second","c-third"},
new string[]{"d-first","d-second","d-third"}
};
Console.WriteLine(myList[0][2]);
Console.WriteLine(myList[2][2]);
}
First you are indexing in list, then in array
myList[ListIndex][ArrayIndex].
It is like shortcut for following:
var stringArray = myList[1];
Console.WriteLine(stringArray[2]);
Accessing that value and printing it to the console would be done like this:
Console.WriteLine(myList[0][2]);
This assumes the array you're accessing is the first one in the List object.

Copy IEnumerables or ICollections into an EXISITING array entry-wise

I have two IEnumerables already filled and an array large enough to store all elements of both of them:
IEnumerable<int> foo = ... // contains some elements.
IEnumerable<int> bar = ... // contains some elements.
int[] array = ... // already existing. array.Length is at least foo.Count + bar.Count
I want to copy the elements of foo and bar into array. And I would like to be able to do this without creating new objects (like LINQ would do when calling Concat or ToArray). In my concrete scenario, I do not care about the order, as it will be sorted later. A way to achieve it is this:
int k = 0;
foreach (int i in foo)
array[k++] = i;
foreach (int i in bar)
array[k++] = i;
I would like to know if there is some built-in method that does the copying for me (for convenience purposes), similar to LINQ ToArray or Concat, but without needing to create new objects. Giving ranges as input would be nice, too. A method like below maybe?
// desired way:
foo.InsertIntoArray(0) // insert the elements of foo into array starting at index 0
bar.InsertIntoArray(foo.Count) // insert the elements of bar into array starting at index foo.Count
I know the Array.Copy method, but as far as I know, it only works to copy from array to array, not from IEnumerable to array. Is there something alike?
List<int> foo = new List<int> { 1, 2, 3 };
List<int> bar = new List<int> { 3, 4, 5 };
//This will give you all items from both collections
var array = Enumerable.Concat(foo, bar).ToArray(); // 1,2,3,3,4,5
var array = foo.Concat(bar).ToArray();
//This will give you all distinct items
var array = Enumerable.Union(foo, bar).ToArray(); //1,2,3,4,5
var array = foo.Union(bar).ToArray();
You can also:
List<int> result = new List<int>();
result.AddRange(foo);
result.AddRange(bar);
result.InsertRange(result.Count, foo);
result.InsertRange(result.Count, bar);
foo.AddRange(bar); //But was assuming you don't want to change the existing list
But Both InsertRange and AddRange reallocate the internal array - And I assume Concut/Union use these behind the scenes
If your IEnumerable object also implements ICollection, you can cast it to ICollection and use the CopyTo method provided by this interface, otherwise you can only write loops. I actually looked at the source code for Enumerable.ToArray, and that's what Microsoft does.

Is this call-by-reference?

I have an ArrayList:
ArrayList ReceivedPackets = new ArrayList();
And I have another ArrayList:
ArrayList returnList = ReceivedPackets;
Why does returnList loose it's value when I run this code?
ArrayList ReceivedPackets = new ArrayList(); // ReceivedPackets is empty
ReceivedPackets.Add(1); // Now it has an Integer
ArrayList returnList = ReceivedPackets; // Call-by-Reference (I thought), returnList now has an Integer
ReceivedPackets.clear(); // returnList is empty now. Why?
When you do this:
ArrayList returnList = ReceivedPackets;
You are creating a new variable called returnList, but this variable points to the same in-memory object as ReceivedPackets. There is still only one actual ArrayList, it just has two variables pointing to it. So changes made to one are reflected in both.
How can I do without returnList loosing it's value?
Create a new object. At its simplest, that would look like this:
ArrayList returnList = new ArrayList();
If you also want that object to contain all the values from ReceivedPackets, fortunately ArrayList has a constructor overload which does just that:
ArrayList returnList = new ArrayList(ReceivedPackets);
Now you'd have two objects which should contain copies of the same data. Changes to one would not be reflected in the other.
In the absence of that constructor, ArrayList also has some CopyTo() methods which can be used to copy elements from one to the other. Failing that, you could also manually loop over the source ArrayList and copy elements to the destination ArrayList.
It's possible that this can get pretty confusing if the ArrayList itself contains reference objects. Because those too may have multiple "pointers" to the same in-memory object.
For example, if you create a single Widget object and add it to two ArrayList objects, then any modifications made to the ArrayList objects (adding/removing elements) would be independent, but any modification made to the Widget object would be reflected in both ArrayLists.
The point is that the ArrayList itself is an object, independent of the objects it contains.
So, depending on the full context of what you're doing, your mileage may vary.
ArrayList is a reference type, meaning that if you simply assign some variable to an instance of it, both objects will point to the same location in memory.
If you want to create deep copy, create a new object.
static void Main() {
ArrayList a = new ArrayList() {1,2,3};
var b = a;
var c = new ArrayList(a);
a.Clear();
Console.WriteLine(a.Count); // 0
Console.WriteLine(b.Count); // 0
Console.WriteLine(c.Count); // 3
}

Information Storage for 3 variables

I am trying to create a good way to store 3 variables, two ints and a point in C# programming.
I thought of a way by using an array of dictionaries
Dictionary<int, Point>[] ItemList = new Dictionary<int, Point>[4];
The Idea was that one variable has to be between 1 and 4, so I would have that as the sorting point, or each array location. The 2nd int, has to be between 0 and 15, and the point is on a 4x4 grid. I thought this method would work, and it would have except that You can't have the same key in a dictionary, and since both ints will be repeated, I can't swap them out. This idea also went out the window, same problem
Dictionary<int, int>[,] ItemList = new Dictionary<int, int>[4,4];
I also thought of using a tuple, and I don't have much(any) experience with it, and my experiments with them weren't going so well. The problem with it was I couldn't get the count of how many items were in it. I set one up like this.
Tuple<int, Point>[] ItemList = new Tuple<int, Point>[4];
Same Idea as my first example, Its just there is no code like this
ItemList[1].Count /*OR*/ ItemList[1].Length
Please let me know if I am missing something terribly obvious with tuples, or suggest an different storage method that would be nice to have all 3 variables stored all together.
You can use the Tuple to store directly the 3 data structures. A Tuple can have more than two items, and of any type. That way, you don't have to use your array:
Tuple<int, int, Point>
To get the values, use the corresponding Item property. For the first int, it will be yourTuple.Item1. For the second one yourTuple.Item2 and for the Point yourTuple.Item3.
If you have multiple Tuples, you can use a classic List to store them all:
var tuples = new List<Tuple<int, int, Point>>();
Since it's a list, you can get the count easily: tuples.Count()
So a class seems like the proper structure to me.
public class Something {
public int Item1 { get; set; }
public int Item2 { get; set; }
public Point Location { get; set; }
}
Then you store these objects in a List<>
var List<Something> list = new List<Something>();
add items to the list...
list.Add(new Something() {Item1 = 4, Item2 = 8, Point = new Point(x,y)});
then use some LINQ to get just the ones you want.
var onlyItem1IsFour = (from item in list where 4 == item.Item1 select item).ToList();
excuse my LINQ. I'm used to VB and may have gotten the casing/syntax slightly wrong
Well, Using the idea of using a list, I solved my problem. Its kinda a hybrid between the suggested ideas and my original idea with using the array. You don't have to use an array if you are looking to do something similar, you can use a tuple with 3 values, I just needed an array for one int value because I needed them stored separately, based off of what that one int value was (between 0 and 4). Here is some code that would work.
List<Tuple<int, Point>>[] ItemList = new List<Tuple<int, Point>>[4]; // how to declare it
for (int i = 0; i < 4; i++)
{
ItemList[i] = new List<Tuple<int, Point>>(); // initilize each list
}
ItemList[1].Add(new Tuple<int, Point>(5, new Point(1, 2))); // add a new tuple to a specific array level
int count = ItemList[1].Count; // finds the count for a specific level of the array --> (1)
int getInt = ItemList[1].ElementAt(0).Item1; // finds int value --> (5)
Point getPoint = ItemList[1].ElementAt(0).Item2; // finds the point --> (1,2)

Accessing array element inside ArrayList c#

I have the following problem,
When i am trying to access data from an Array inside another Array List, it dispalys that "cannot apply indexing[] with to an expression of type 'object'".
This is my code
public void getWaypoints() {
ArrayList potentialWPs = new ArrayList();
potentialWPs.Add(containerWaypoint.GetComponentInChildren(typeof(Transform)));
wayPoints = new ArrayList();
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints[wayPoints.Count] = new ArrayList(2);
wayPoints[wayPoints.Count][0] = potentialWP;
}
}
The error are shown in the line "wayPoints[wayPoints.Count][0]".
Any one have any idea why this error is occurred?
Since ArrayList is a non-generic collection class, all items retrieved from it are objects, and need to be cast to their real types, like this:
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints[wayPoints.Count] = new ArrayList(2);
ArrayList arr = wayPoints[wayPoint.Count] as ArrayList; <-- THIS
arr[0] = potentialWP;
}
Several important things to note:
1) This would have been simpelr if you had simply created the new array and held a reference to it (the arr variable I introduced) and then used that to add to the wayPoints and to assign to.
2) ArrayList really is an old and primitve class. Is there a reason you don't use a List<Transform> instead>?
3) You have a bug in your code, since you're access the ArayList in position Count. An ArrayList of length 2, if accessed at position 2, will crash - ArrayLists are 0-based, so you need to use Count - 1 to access the last position (1) on a length 2 array.
Try this wayPoints[0] = potentialWP;
Since you have already declared an array list with size wayPoints.Count , you have to mention the index correctly.
An ArrayList only holds object types; that why you get
"cannot apply indexing[] with to an expression of type 'object'"
You need to cast
wayPoints
to your desired type
EDIT:
You should be using
List<T> (System.Collections.Generics)
wayPoints[wayPoints.Count] = new ArrayList(2);
wayPoints[wayPoints.Count][0] = potentialWP;
wayPoints[wayPoints.Count] returns an object. You need to cast it, before treating it like an ArrayList:
((ArrayList)wayPoints[wayPoints.Count])[0] = potentialWP;
However, you shouldn't use ArrayList, as it's deprecated. Use List instead.
The main problem you have is that by using ArrayList which is just a collection of objects, there is no implicit conversion to an array. As others have answered, one way is to cast the result to an array, after which you can access it by index.
A better way, might be to use a Generic List<T> which can be defined as a list of lists:
List<List<Transform>> waypoints = new List<List<Transform>>();
This would make your code a lot easier:
public void getWaypoints() {
ArrayList potentialWPs = new ArrayList();
potentialWPs.Add(containerWaypoint.GetComponentInChildren(typeof(Transform)));
List<Transform[]> waypoints = new List<Transform[]>();
foreach (Transform potentialWP in potentialWPs){
if(potentialWP.transform != containerWaypoint.transform){
wayPoints.Add( new List<Transform>>(){ potentialWP });
}
}
}
waypoints is now a "multi-dimensional" list of lists of Transform. You can access any element like so
List<Transform> first = waypoints[0];
or you could access a Transform directly
Transform firstOfFirst = waypoints[0][0];
or you could add another Transform to an existing list
waypoints[0].Add(anotherTransform);

Categories