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.
Related
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.
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.
In C#, I have a string array that I have written full full of "getter" method calls. They call methods in another class so that the array is populated with the needed strings. It looks something like this:
string[] mCalls = {c.get1(), c.get2(), c.get3()};
I'm sure this situation could apply to any program. However, in my program the variables these methods return are initially set with the string "Unchecked" - thus filling this example array with Unchecked 3 times. As my program goes on and things are checked, the values of the string variables get changed within the class they're in. I've been simply re-calling the getter methods at appropriate times to change what's in my array, like this:
mCalls[0] = c.get1();
mCalls[1] = c.get2();
mCalls[2] = c.get3();
I don't really like this. It seems inevitable that one day I'll have to change something, and if that happens I will have to manually do the tedious work of changing all of the indexing throughout my program. If this happens to be the best way I'm fine with that, but I assume there are better ways. So, in any case, is there a way to "refresh" the values in an array that is set up like this? And if so, what is it?
You want something like this:
public string[] MCalls
{
get
{
return new string[]{c.get1(), c.get2(), c.get3()};
}
private set;
}
and then use MCalls as if it is a regular variable whenever you want to access the arrays
You could change your array to contain functions instead of strings like this:
Func<string>[] mCalls = { c.get1, c.get2, c.get3...};
And then use it this way:
string c2 = mCalls[1]();
But note that this way every access is a method call. I'm not sure what you are really trying to achieve, there may be better overall designs than this approach.
Couple of options:
Create an array of lambdas:
var mCalls = new Func<object, string>[] {
(object o) => o.ToString() ,
(object o) => o.GetHashCode().ToString(),
(object o) => o.GetType().ToString(),
};
If the input to each lambda is the same you can create a lambda that returns an array:
Func<object, string[]> GetValues = (object o) => new string[]
{
o.ToString() ,
o.GetHashCode().ToString(),
o.GetType().ToString(),
};
Then just reload the array by calling the lambda:
mCalls = GetValues(c);
Note that it isn't technically refreshing the array, it's creating a new array. If you need to keep the array the same but just update the values you'd ned to loop through the array and assign the values by index.
What you could do is loop thorugh with reflection and get all methods from the class and from here you can get a list of method names. With this list you can assign to an array or run the methods by name or whatever. You can also filter the list to get your specific method names only:
var methodNames = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
To call the methods:
foreach(var method in methodNames)
{
typeof(MyClass).GetMethod(method).Invoke(t, new[] { "world" });
}
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);
Sorry, I think I was not clear earlier. I am trying to do as O.R.mapper says below- create a list of arbitrary variables and then get their values later in foreach loop.
Moreover, all variables are of string type so I think can come in one list. Thanks.
Is there a way to store variables in a list or array then then loop through them later.
For example: I have three variables in a class c named x,y and Z.
can I do something like:
public List Max_One = new List {c.x,c.y,c.z}
and then later in the code
foreach (string var in Max_One)
{
if ((var < 0) | (var > 1 ))
{
// some code here
}
}
Is there a particular reason why you want to store the list of variables beforehand? If it is sufficient to reuse such a list whenever you need it, I would opt for creating a property that returns an IEnumerable<string>:
public IEnumerable<string> Max_One {
get {
yield return c.x;
yield return c.y;
yield return c.z;
}
}
The values returned in this enumerable would be retrieved only when the property getter is invoked. Hence, the resulting enumerable would always contain the current values of c.x, c.y and c.z.
You can then iterate over these values with a foreach loop as alluded to by yourself in your question.
This might not be practical if you need to gradually assemble the list of variables; in that case, you might have to work with reflection. If this is really required, please let me know; I can provide an example for that, but it will become more verbose and complex.
Yes, e.g. if they are all strings:
public List<string> Max_One = new List<string> {c.x,c.y,c.z};
This uses the collection initializer syntax.
It doesn't make sense to compare a string to an int, though. This is a valid example:
foreach (string var in Max_One)
{
if (string.IsNullOrEmpty(var))
{
// some code here
}
}
If your properties are numbers (int, for example) you can do this:
List<int> Max_One = new List<int> { c.x, c.y, c.Z };
and use your foreach like this
foreach(int myNum in Max_One) { ... } //you can't name an iterator 'var', it's a reserved word
Replace int in list declaration with the correct numeric type (double, decimal, etc.)
You could try using:
List<object> list = new List<object>
{
c.x,
c.y,
c.z
};
I will answer your question in reverse way
To start with , you cannot name your variable with "var" since it is reserved name. So what you can do for the foreach is
foreach (var x in Max_One)
{
if ((x< 0) || (x> 1 ))
{
// some code here
}
}
if you have .Net 3.0 and later framework, you can use "var" to define x as a member of Max_One list without worrying about the actual type of x. if you have older than the version 3.0 then you need to specify the datatype of x, and in this case your code is valid (still risky though)
The last point (which is the your first point)
public List Max_One = new List {c.x,c.y,c.z}
There are main thing you need to know , that is in order to store in a list , the members must be from the same datatype, so unless a , b , and c are from the same datatype you cannot store them in the same list EXCEPT if you defined the list to store elements of datatype "object".
If you used the "Object" method, you need to cast the elements into the original type such as:
var x = (int) Max_One[0];
You can read more about lists and other alternatives from this website
http://www.dotnetperls.com/collections
P.s. if this is a homework, then you should read more and learn more from video tutorials and books ;)