C# Changing a part of a line of code to a variable - c#

I am using Unity3D.
I have a script to sort a list based on a certain value of a creature.
For example, the creatures have a variable saying how much food they've eaten, how many calories they currently have, and how large they are.
I want the user to be able to change the way the values are sorted by clicking a button. I don't want to pile if statements though, such as
if(sortType == "calories") {
entrySortedText.text = creatureData.calories.ToString();
} else if(sortType == "food eaten") {
entrySortedText.text = creatureData.foodEaten.ToString();
}
I want to be able to do something like
entrySortedText.text = creatureData.sortType.ToString();
to automatically find the variable with the name of what the sort type is in creatureData. But obviously this doesn't work, as there is no variable "sortType" in creature data, but I want it to replace what the sortType is automatically with the variable name, such as "calories" or "food eaten".
Does anyone know a way to change a part of a line of code to the value of a variable? Or do I have to just use a bunch of if statements?
Thanks. Your response is greatly valued.
P.S.
Here is the current sorting code:
public void LoadList() {
foreach(Transform child in transform) {
GameObject.Destroy(child.gameObject);
}
List<GameObject> creatures = new List<GameObject>(GameObject.FindGameObjectsWithTag("Creature").ToList());
// Sort list based on calories
creatures.Sort(
delegate(GameObject i1, GameObject i2) {
return i2.GetComponent<CreatureData>().calories.CompareTo(i1.GetComponent<CreatureData>().calories);
}
);
foreach(GameObject creature in creatures) {
GameObject entry = Instantiate(entryPrefab);
entry.transform.SetParent(transform, false);
entry.transform.GetChild(0).GetComponent<Text>().text = creature.GetComponent<CreatureData>().creatureName;
entry.transform.GetChild(1).GetComponent<Text>().text = creature.GetComponent<CreatureData>().calories.ToString();
entry.GetComponent<CreatureListEntryButton>().targetCreature = creature;
}
}

So you want to sort on a property but that property will be decided at runtime.
Let's say you have a collection named items and the items have a property named Calories. Then you can do this:
var sortBy = "Calories";
var propertyInfo = typeof(YourObject).GetProperty(sortBy);
Then you can sort on that:
var orderByCalories = items.OrderBy(x => propertyInfo.GetValue(x, null));

Related

Does expanding arraylist of objects make a new object?

Assume we have an array list of type Employe , does expanding it's length by 1 make a new object in the list ?
is the code in else statement correct? and is it recommended?
public void ModifierEmp(int c)
{
for(int i = 0; i < Ann.Count; i++)
{
if(Ann[i].Code == c)
{
Ann[i].saisie();
} else
{
i = Ann.Count + 1; //expanding arraylist ann
Ann[i].saisie(); //saisie a method for the user to input Employe infos
}
}
}
https://imgur.com/VfFHDKu "code snippet"
i = Ann.Count + 1;
The code above is not expanding the list: it is only setting your index variable (i) to have a new value.
If you wanted to make the list bigger, you would have to tell it which object to put into that new space you create. For example:
Ann.Add(anotherItem);
Of course, this gives you the ability to decide whether to add an existing item, create a new item (e.g. Ann.Add(new Something() { Code = c })), or even add a null value to the list (which is not usually a good idea).

C# listbox item identification

Keep in mind, i am not very experienced with c#.
I am coding a remove button for a list box and the basic function of removing the selected item works.
listBoxSum.Items.RemoveAt(listBoxSum.SelectedIndex);
I'm trying to make an IF statement which will allow me to select an item from my list-box and have it identify the text inside of it (Most likely a string).
As i don't know too much about c#, this is what i currently have for the if statement (obviously the first line is error).
if (listBoxSum.SelectedItem = "Tea")
{
totalCost = totalCost - teaCost;
txtBox_Amount.Text = totalCost.ToString();
}
I have tried making other strings to help simplify the statement like (Below is not the main piece of code for the if statement, the above code is. This was just an experiment on try and extend the code to make it a bit more understandable for myself):
string teaSelect = "Tea" + teaCost;
string selection = (string) listBoxSum.SelectedItem;
if (selection == teaSelect)
{
totalCost = totalCost - teaCost;
txtBox_Amount.Text = totalCost.ToString();
}
Please help, i don't know whether i should change how i'm thinking about this or if it an easy fix hiding in plain sight. Personally i have been stumped on this little button for around 2 hours figuring out how i am going to make the remove button work with the calculations.
If you are not updating your item that holds the "Tea + cost" value, you should probably identify it either by string.StartsWith or maybe assigning it with an identifier of your choice. This could be an integer, an enum or another concrete class with predefined instances.
You can do this by using the Tag property for WPF and creating a simple class for Windows Forms (WPF Tag Property).
A simple example for Windows Forms would be:
enum FoodType
{
Tea = 2
}
class FoodItem
{
public string Text { get; set; }
public FoodType FoodType { get; set; }
public override string ToString()
{
return Text;
}
}
When you are adding your items:
listBoxSum.Items.Add(new FoodItem
{
FoodType = FoodType.Tea,
Text = "Tea " + teaCost
});
And when you are filtering them:
if (listBoxSum.SelectedItem is FoodItem foodItem && foodItem.FoodType == FoodType.Tea)
{
// Do work
}
It is even easier for WPF:
enum FoodType
{
Tea = 1
}
Adding items:
listBoxSum.Items.Add(new ListBoxItem
{
Content = "Tea " + teaCost,
Tag = FoodType.Tea
});
Identifying items:
if (listBoxSum.SelectedItem is ListBoxItem foodItem && foodItem.Tag is FoodType foodType && foodType == FoodType.Tea)
{
MessageBox.Show("hi");
}
What you want to check is whether the item you are currently looking at is a ListBoxItem, and if so, is the contained content a text and is this text equal to your desired text, in order to identify the correct item.
var content = (((x.SelectedItem as ListBoxItem)?.Content as string);
if (content != null && content == "MyDesiredText") {...}
This would be a valid, but not an elegant solution.
A better way would be to remember the listbox items while creating them
var desiredListBoxItem = new ListBoxItem(...)
x.AddChild(desiredListBoxItem);
and afterwards, check whether the object references match:
if (x.SelectedItem == desiredListBoxItem) {...}
So your item in ListBox is called "Tea"?If it is your if statement should look something like this:
if(yourTextBox.Items[yourTextBox.SelectedIndex] == "Tea")
{
//Your Code
}

How to create multidimensional variable list of objects using recursion in C#?

I am trying to generate in C# a multidimensional sequence of possible actions objects might make in 1 turn, with a variable amount of objects, and a variable amount of actions available to the object.
each object should make 1 action each turn.
For Example: - where object is the letter, and the action it can do is the number:
possible objects/actions: a1,a2,a3,b1,c1
I have a list of Actions which have an Object as a property
I would like the multidimensional list to look like this:
a1,b1,c1
a2,b1,c1
a3,b1,c1
b1,a1,c1
b1,a2,c1
b1,a3,c1
c1,a1,b1
.....
When I started coding the function to return a multidimensional list of Actions, i realised how out of my depth i was, and so i have come here!
My current code:
private List<List<Move>> PotentialLine(List<Move> moves, List<Move> currentList = null, List<List<Move>> finalList = null)
{
if(finalList == null)
finalList = new List<List<Move>>();
if(currentList == null)
currentList = new List<Move>();
//find all combinations of move for this level
foreach(Move move in moves.ToList())
{
currentList.Add(move);
List<Move> movesRemaining = moves;
movesRemaining.RemoveAll(o=> o.card == move.card);
if(!movesRemaining.Any())
{
finalList.Add(currentList);
return finalList;
}
else
{
finalList = PotentialLine(movesRemaining, currentList, finalList);
}
}
return finalList;
}

Specified Cast Not Valid - XamarinFirebase

This is my firebase database structure
Database Structure
In the child, there are values , Name, Country, Age and Uid. The Uid is the focus in my question.
I am try to fetch the children of the node (Chat) based on the current logged in user.
I am basically trying to do a comparison here that, firebase should get me children who only have the Uid = user.uid. i.e the current logged in user. I thought Equals() could do the trick but i get an error with the cast.
The error points at this line var items = snapshot.Children?.ToEnumerable<DataSnapshot>().Equals(user.uid).ToString;
public void OnDataChange(DataSnapshot snapshot)
{
var items = snapshot.Children?.ToEnumerable<DataSnapshot>().Equals(user.uid).ToString;
var key = snapshot.Key;
HashMap map;
foreach (DataSnapshot item in items)
{
}
Console
my snapshot test: DataSnapshot { key = Chat, value = {-KomfGbZxCGESgyo1PFT={Name=Testing , Ref=7YB3mxMRXxW4lzhbhxi1bx7K4Pf1,
}, -KomcJyR5dCxFucJSB0I={Name=Hi, Ref=K6TEpccn1TbB32T8ThFsYnIl6Wm2, }} }
If you want to filter the user based on Ref attribute, I suggest you make an if-statement inside foreach loop to filter the item:
public void OnDataChange(DataSnapshot snapshot)
{
var items = snapshot.Children?.ToEnumerable<DataSnapshot>();
HashMap map;
foreach (DataSnapshot item in items)
{
//filter the user first
map = (HashMap)item.Value;
string userId = map.Get("Ref")?.ToString();
if (userId!=null&& userId == user.uid)
{
//do what you want to do here.
}
}
When you use ToEnumerable, the type of returned objects is DataSnapshot and it cannot be compared to user.uid. You might want to use linq to grab what you wants. something like:
var items = snapshot.Children?.ToEnumerable(x=> x.uid == user.uid)

C# Linking element of List

I'm thinking of a way to create a link or reference to a List of Strings. My situation is that I'm creating ARP table and I need to save IP (as String) of my interface that captured response msg. Interface's IP address is saved in List<String>.
ARP_Table_entry(System.Net.IPAddress host_ip_addr, System.Net.NetworkInformation.PhysicalAddress host_mac_addr, int position)
{
this.host_ip_addr = host_ip_addr;
this.host_mac_addr = host_mac_addr;
this.time = System.DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
this.local_inter = ??;
}
What I don't want to do, is to assign local_inter smt like list.ElementAt(0), because when I change IP address on the interface (List gets updated w/ new one), value in entry won't change - and I would have to do foreach for every entry (not bad, but...)
Instead I'm looking for solution, that will "link" that specific List-element to local_inter parameter - so changing IP in List will result in automatic update in every entry that contained old one.
If you can control code for ARP_Table_entry just make local_inter property that returns value from that mysterious list:
class ARP_Table_entry
{
List<string> mysteriousList;
int pos;
public ARP_Table_entry(List<string> mysteriousList, int pos,...)
{
this.mysteriousList = mysteriousList;
this.pos = pos;
...
}
// TODO: add null check/position verification as needed
string local_inter => mysteriousList[pos];
// or {get { return mysteriousList[pos];} for C# 5 and below
...
You can also use Func<string> as type or local_inter if you want to use fields for some reason:
class ARP_Table_entry
{
public Func<string> local_inter;
...
public ARP_Table_entry(List<string> mysteriousList, int pos,...)
{
local_inter = () => mysteriousList[pos];
...
}
Note that either approach will not protect you from replacing list altogether with originalMysteriousList = new List<string>().
Another option is to have more complex type to store list of IPs that will notify about its changes (similar to ObesrvableCollection) and update fields on change in the collection.

Categories