Nested Lists in Unity 3d- How do I do this? - c#

Bryce: Here are my current functions. With the list in the class, I'm not quite sure how to modify my code.
public void GetMembers()
{
DatabaseManager.Instance.SQLiteInit();
MemberList.Clear();
MemberList= DatabaseManager.Instance.MakeMembersList();
Debug.Log("How many in the list " + MemberList.Count);
ShowAllMembers();
}
public void GetEquipment()
{
DatabaseManager.Instance.SQLiteInit();
EquipmentList.Clear();
EquipmentList= DatabaseManager.Instance.MakeEquipmentList();
Debug.Log("How many in the list " + EquipmentList.Count);
ShowAllEquipment();
}
Also thought you should see the database function being called.
public List<NewEquipmentClass> MakeEquipmentList()
{
EquipmentList.Clear();
mConnection.Open();
mSQLString = "SELECT * FROM " + SQL_TABLE_EQUIPMENT + " ORDER BY " + COL_EQUIPMENT_ID;
mCommand.CommandText = mSQLString;
mCommand.ExecuteNonQuery();
mReader = mCommand.ExecuteReader();
while (mReader.Read())
{
EquipmentList.Add(new Equipment(mReader.GetString(0),
mReader.GetString(1)));
Debug.Log(mReader.GetString(0) + mReader.GetString(1));
}
mReader.Close();
mConnection.Close();
return EquipmentList;
}
Thanks!
This is the result I am looking for:
Member Name
Member's Equipment
Member's Equipment
Member's Equipment
Member Name
Member's Equipment...
Etc.
I have two lists, one for members and one for equipment. What is the best way to get the type of results above?
Thanks!

It looks like you want to create a class called Member that looks something like this
class Member {
string name;
List<Equipment> equipment;
}
where Equipment could be an object with a name and stats or whatever you need. And then have a list of them like
List<Member> members;
Obviously you'd want getters/setters/constructor etc. but if implementing this isn't clear to you I'd recommend some fundamentals of c# or Object Oriented learning.

Related

How to deal with a position in list that doesn't exist?

I'm building this program in C# in which you can enter membership details, confirm them, and view previously stored memberships. I am still very much a beginner and this is just some school homework.
My teacher suggested to write and read membership details to a file but I had no idea how to do this efficiently so just added them all to a list. I wrote this part to retrieve the username, password and membership type.
However, how do I stop an 'unhandled' error if the user enters a value in which doesn't have any stored data?
Here is the code: the list is called membersList.
Console.WriteLine("Which stored membership would you like to view? (e.g 1, 2..)");
int membChoice = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Membership Entry " + membChoice);
Console.WriteLine("Username: " + membersList[membChoice*3-3]);
Console.WriteLine("Password: " + membersList[membChoice*3-2]);
Console.WriteLine("Membership Type: " + membersList[membChoice*3-1].ToUpper());
This results in an unhandled exception error if you enter a larger value than members already stored.
You will first need to check if the list has an element at the position you want:
if(list.ElementAtOrDefault(membChoice*3-3) != null)
{
Console.WriteLine("Username: " + membersList[membChoice*3-3]);
}
That or you can do a try catch to catch the error and display something like invalid choice.
I don't think your list is efficient. I understand you save three information for the same object in three different indices.
I think a better way for comprehension when we begin to code, is to create a class for handle all of this information, like a Member class:
class Member
{
public int ID { get; set; }
public string Name { get; set; }
public string Password { get; set; }
public string Type { get; set; }
}
And use this class for ONLY ONE index of your list:
Member member = new Member()
{
ID = 0,
Name = "Monty Python",
Password = "My favorite color is blue",
Type = "Knight"
};
List<Member> membersList = new List<Member>();
membersList.Add(member);
After you can retrieve data by searching with ID:
User userFind = membersList.Find(x => x.ID == membChoice);
And then display data:
Console.WriteLine("UserName : " + userFind.Name);

Trying to understand Generic List in C# [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 months ago.
Improve this question
I hope everyone is well.
I have some practice code here that I've been working on and the code works and I have no issues with it however, I don't find that I fully understand what I've written and why it works.
I want to try and be able to understand my work so that I can become a better programmer, I've left comments for the code that I dont fully understand, the rest I am comfortable with.
I would appreciate any one with the spare time to give me a few pointers and some help, thank you very much.
namespace GenericList
{
class Program
{
static void Main(string[] args)
{
/* I understand how objects work, but I dont fully understand
what is happening when I am passig through my constructer
name through the List */
List<Cities> cities = new List<Cities>();
/* I am passing matching arguments through each instance
of my cities List object but I still struggle to
visualise this process */
cities.Add(new Cities(1, "Durban - Home to the largest harbor in Africa"));
cities.Add(new Cities(2, "Johannesburg - The largest city in the country"));
cities.Add(new Cities(3, "Gqebetha - Also known as P.E, the friendly city"));
cities.Add(new Cities(4, "Bloemfontien - Host of the Rose Festival"));
cities.Add(new Cities(5, "Pretoria - South Africa's capital"));
Console.WriteLine("Which city would you like to know an interesting fact for?" +
"\n1) Durban" +
"\n2) Johannesburg" +
"\n3) Gqebetha" +
"\n4) Bloemfontien" +
"\n5) Pretoria" +
"\nEnter the number for the city you want:");
int answer = int.Parse(Console.ReadLine());
bool found = false;
for (int i = 0; i < cities.Count; i++)
{
if (cities[i].Id.Equals(answer))
{
Console.WriteLine("\nANSWER: " + cities[i].City);
found = true;
}
}
if (!found)
{
Console.WriteLine("\nWe couldn't find what you are looking for.");
}
}
}
class Cities
{
int id;
string city;
public Cities(int id, string city)
{
this.id = id;
this.city = city;
}
public int Id { get => id; set => id = value; }
public string City { get => city; set => city = value; }
}
}
List<Cities> cities = new List<Cities>();
Here you are creating a List, which contains only the object of Cities's class.
List is a array type data structure with various utilities(method).
Here you are using Add(), which append a new object to the list (in that case only Cities object as you declare in first line List<Cities>).
cities.Add(new Cities(1, "Durban - Home to the largest harbor in Africa"));
If I break down this line this will be:
// Creating a new Cities object
var newCity = new Cities(1, "Durban - Home to the largest harbor in Africa");
cities.Add(newCity );
Last line from the code block is appending newCity to the list of cities
Hope you understand now, If anything left unclear let me know
i rewrote with linq so you can see as a different approach. more easy reading code
void Main()
{
List<Cities> cities = new List<Cities>();
//add to cities array a new City class, since constructor accept 2 parameters you supply them on new object creation
Cities city;
city = new Cities(1, "Durban - Home to the largest harbor in Africa");
cities.Add(city);
city = new Cities(2, "Johannesburg - The largest city in the country");
cities.Add(city);
city = new Cities(3, "Gqebetha - Also known as P.E, the friendly city");
cities.Add(city);
city = new Cities(4, "Bloemfontien - Host of the Rose Festival");
cities.Add(city);
city = new Cities(5, "Pretoria - South Africa's capital");
cities.Add(city);
//different approach: create list with objects
cities = new List<Cities>()
{
new Cities(1, "Durban - Home to the largest harbor in Africa"),
new Cities(2, "Johannesburg - The largest city in the country"),
new Cities(3, "Gqebetha - Also known as P.E, the friendly city"),
new Cities(4, "Bloemfontien - Host of the Rose Festival"),
new Cities(5, "Pretoria - South Africa's capital")
};
Console.WriteLine("Which city would you like to know an interesting fact for?" +
"\n1) Durban" +
"\n2) Johannesburg" +
"\n3) Gqebetha" +
"\n4) Bloemfontien" +
"\n5) Pretoria" +
"\nEnter the number for the city you want:");
int answer = int.Parse(Console.ReadLine());
var result = cities
.Select((obj, index) => new { index, obj }) //set index for each object
.Where(w => w.index == answer)
.FirstOrDefault();
if (result == null)
Console.WriteLine("\nWe couldn't find what you are looking for.");
else
Console.WriteLine("\nANSWER: " + result.obj.City);
}
class Cities
{
//class properties
public int Id { get; set; }
public string City { get; set; }
//Parameterized Constructor https://www.tutlane.com/tutorial/csharp/csharp-constructors-with-examples#divcspzcst
public Cities(int id, string city)
{
Id = id;
City = city;
}
}
With
List<Cities> cities = new List<Cities>();
you create a new List-object that can store Cities objects. The generic type parameter <Cities> denotes the type of the list items and does not refer to the constructor. As an example, the following code would create a list that could store integer values:
List<int> lst = new List<int>();
The List<T> class is a generic type. The basic operations for a list like adding, removing, enumerating and so on are the same no matter what the type of the list items is. By creating a generic type, you can implement the functionality without knowing which types are used later on when you create an object. You might compare this to a method: when you implement the method, you define the parameters and their types; when you call the method, you supply the values of the parameters.
The code in the following line performs two tasks:
cities.Add(new Cities(1, "Durban - Home to the largest harbor in Africa"));
First, a new object of type Cities is created and initialized through the constructor. Second, it is added to the list. These are two separate steps that can also written like this:
// Create new object of type Cities
var city = new Cities(1, "Durban - Home to the largest harbor in Africa");
// Add newly created object to list
cities.Add(city);
As #BinRohan suggested in the comments, it might be a good idea the rename the Cities class to City because it defines a single city, not a collection of cities.
When you write this line of code
List<Cities> cities = new List<Cities>();
You instantiate an object being a List of "Cities". List is a "generic" type. It means it is able to handle any type and will behave the same. You could have a List or List, you'll manipulate different objects but the behaviour of List remains the same. You are not "passing" Cities to the List constructor, consider List as a type in itself.
It would be equivalent of declaring an array of Cities for example. There is no data in your list yet but it is ready to receive multiple instance of Cities.
Then when you write
cities.Add(New Cities{prop1=value,prop2=value...});
at run time it will do something like
var c = new Cities();
c.prop1=value;
c.prop2=value;
cities.Add(c);
It's kind of a shortcut which also make the code more readable.

Get specific values of a struct/List

I'm creating a game in Unity3D + C#.
What I've got at the moment: an SQL datatable, consisting of 8 columns holding a total of 3 entries and a list "_WeapList" that holds every entry (as shown below).
public struct data
{
public string Name;
public int ID, dmg, range, magazin, startammo;
public float tbtwb, rltimer;
}
List<data> _WeapList;
public Dictionary<int, data>_WeapoList; //probable change
[...]
//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
{
data itm = new data();
itm.Name = rdr["Name"].ToString();
itm.ID = int.Parse (rdr["ID"].ToString());
itm.dmg = int.Parse (rdr["dmg"].ToString());
itm.range = int.Parse (rdr["range"].ToString());
itm.magazin = int.Parse (rdr["magazin"].ToString());
itm.startammo = int.Parse (rdr["startammo"].ToString());
itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
itm.rltimer = float.Parse(rdr["rltimer"].ToString());
_WeapList.Add(itm);
_WeapoList.Add(itm.ID, itm);//probable change
}
Now I want to create a "Weapon"-Class that will have the same 8 fields, feeding them via a given ID
How do I extract the values of a specific item (determined by the int ID, which is always unique) in the list/struct?
public class Weapons : MonoBehaviour
{
public string _Name;
public int _ID, _dmg, _range, _magazin, _startammo;
public float _tbtwb, _rltimer;
void Start()
{//Heres the main problem
_Name = _WeapoList...?
_dmg = _WeapoList...?
}
}
If your collection of weapons may become quite large or you need to frequently look up weapons in it, I would suggest using a Dictionary instead of a List for this (using the weapon ID as the key). A lookup will be much quicker using a Dictionary key than searching through a List using a loop or LINQ.
You can do this by modifying your code to do this as follows:
public Dictionary<int, data>_WeapList;
[...]
//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
{
data itm = new data();
itm.Name = rdr["Name"].ToString();
itm.ID = int.Parse (rdr["ID"].ToString());
itm.dmg = int.Parse (rdr["dmg"].ToString());
itm.range = int.Parse (rdr["range"].ToString());
itm.magazin = int.Parse (rdr["magazin"].ToString());
itm.startammo = int.Parse (rdr["startammo"].ToString());
itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
itm.rltimer = float.Parse(rdr["rltimer"].ToString());
_WeapList.Add(itm.ID, itm);//probable change
}
Then, to access elements on the list, just use the syntax:
_WeapList[weaponID].dmg; // To access the damage of the weapon with the given weaponID
Guarding against invalid IDs:
If there's a risk of the weaponID supplied not existing, you can use the .ContainsKey() method to check for it first before trying to access its members:
if (_WeapList.ContainsKey(weaponID))
{
// Retrieve the weapon and access its members
}
else
{
// Weapon doesn't exist, default behaviour
}
Alternatively, if you're comfortable using out arguments, you can use .TryGetValue() instead for validation - this is even quicker than calling .ContainsKey() separately:
data weaponData;
if (_WeapList.TryGetValue(weaponID, out weaponData))
{
// weaponData is now populated with the weapon and you can access members on it
}
else
{
// Weapon doesn't exist, default behaviour
}
Hope this helps! Let me know if you have any questions.
Let specificWeapon be a weapon to be searched in the list, then you can use the following code to select that item from the list of weapons, if it is not found then nullwill be returned. Hope that this what you are looking for:
var selectedWeapon = WeapList.FirstOrDefault(x=> x.ID == specificWeapon.ID);
if(selectedWeapon != null)
{
// this is your weapon proceed
}
else
{
// not found your weapon
}
You can use LINQ to search specific object through weaponId
var Weapon = _WeapList.FirstOrDefault(w=> w.ID == weaponId);

Strong-type new object after LINQ select statement

This is not a critical concept for me but I was just
wondering if I could strong-type a new object after linq select statement, rather than make it anonymous type, in C#. Here is an sample, defunct of course but speaks to the concept:
public class DisplayAddress { public int AddressId; public string ShortAddress; }
List<DisplayAddress> shortAddresses =
(from la in longAddresses
join ca in customerAddresses
on la.AddressId equals ca.AddressId
where ca.CustomerId == selectedCustomer
select new { new DisplayAddress() {AddressId = la.AddressId, ShortAddress = la.Line1 + " " + la.City + " " + la.State}}).Tolist<DisplayAddress>();
Absolutely, you can use any expression in the Select, including one that creates a new object of a type that you defined. All you need to do is removing the outer new:
select new DisplayAddress {
AddressId = la.AddressId
, ShortAddress = la.Line1 + " " + la.City + " " + la.State
}).Tolist();
Note that anonymous types are strongly typed as well. In other words, if you do
select new {
AddressId = la.AddressId
, ShortAddress = la.Line1 + " " + la.City + " " + la.State
}).Tolist();
your anonymous type would have two strongly-typed fields called AddressId and ShortAddress. The only difference is that you would need to consume anonymous objects in the context where you create them in order to preserve strong typing. In other words, you would not be able to pass the results of anonymous Select to a non-generic function without using dynamic, object, etc.
Your example code was really close. You over-complicated a few things which were probably your downfall.
In your select clause, rather than defining a new { new DisplayAddress() ... } just do new DisplayAddress(). (You were effectively boxing your DisplayAddress in another unnecessary object. There's also the compiler error of not defining what the member name of that property was.)
At the end of your query, you were doing Tolist<DisplayAddress>(). Couple of issues:
The method is ToList() and capitalization matters in C#. :)
Because you specified DisplayAddress in your Tolist<DisplayAddress>() call, it was causing a compiler error because you can't convert your anonymous type to a strong type of DisplayAddress.
After you address all of these small issues, you come up with the following:
var shortAddresses = (from la in longAddresses
join ca in customerAddresses
on la.AddressId equals ca.AddressId
where ca.CustomerId == selectedCustomer
select new DisplayAddress()
{
AddressId = la.AddressId,
ShortAddress = la.Line1 + " " + la.City + " " + la.State
}).ToList();

looping through elasticsearch queryresult using Mpdreamz/NEST

Iam using Mpdreamz/NEST as .net client for searching elasticsearch.
I am getting the result count of search result using result.Hits.Total. But I am wondering how I can display the value of a field from the result.
var result = client.Search(....)
Will return a a QueryResult<dynamic> with a Documents property of type IEnumerable<dynamic> You can loop over this like so:
foreach(var d in result.Documents)
{
Console.WriteLine(d.title);
}
The casing matters here d.Title will result in a RuntimeBinderException. Unless your elasticsearch field actually exactly matches 'Title`
You can also map to POCO's
public class MyResult
{
public string Title { get; set; }
}
...
var result = client.Search<MyResult>(....)
Now Documents is a IEnumerable<MyResult> which will give you compile time guarantees the property exists.
You should not have to access .Fields["field"] unless you are dealing with user input.
result.Total is also preferred over result.Hits.Total
Looking at NEST source code, it seems that you could do something like:
foreach (var item in result.Documents.ToList())
{
string msg = "Name: " + item.Name + " | Value: " + item.Text;
alert(msg);
}

Categories