5

Let's say I have an object MyCharacter of the class Character, which has the following properties: Health, Mana, MoveSpeed.
From a different method I get a string that contains these stats as follows:
"Health: 100 Mana: 100 MoveSpeed: 100"
I now want to assign these stats to my object. My current attempt is this:

// stats is the string I showed above
var statsArray = stats.Split(' ');
for (var i = 0; i < statsArray.Length; i++)
{
    switch(statsArray[i])
    {
        default:
            break;
        case "Health:":
            MyCharacter.Health = statsArray[i+1];
            break;
        case "Mana:":
            MyCharacter.Mana = statsArray[i+1];
            break;
        case "MoveSpeed:":
            MyCharacter.MoveSpeed = statsArray[i+1];
            break;
    }
}

The thing now is, that I know the order of the stats. It's always Health, then Mana, then MoveSpeed. So I am looking for a way to simplify it, namely getting rid of this switch (since the actual Character here has 18 stats and it's not exactly good looking as it is).
My idea would be going through the array and tell the program to assign the first number it finds to Health, the second to Mana and the third to MoveSpeed.
Is anything like that even possible?

Wilsu
  • 348
  • 1
  • 3
  • 18
  • 2
    Do you now have any concern / performance / error on using switch case? why you would like to change?? If not, to me, I would prefer using switch case, it's easier for debugging and reading – User2012384 Nov 16 '15 at 09:45
  • If you know the correct order, why have the labels in the first place? Is there a reason not to have e.g. `100,100,100`? – Luaan Nov 16 '15 at 09:49
  • The only way your going to be able to dynamically load into properties without knowing their names up front is to [use reflection (with the associated performance hit and complexity increase)](http://stackoverflow.com/questions/771524/how-slow-is-reflection). TBH I see nothing wrong with how it is now. [Any fool can write code that a computer can understand. Good programmers write code that humans can understand](http://stackoverflow.com/questions/522828/is-code-for-computers-or-for-people) – Liam Nov 16 '15 at 09:50
  • Another option if stats is a string is to use a string object notation, like Json, that way you can make your [stringly typed object](http://blog.codinghorror.com/new-programming-jargon/) more explicit. – Liam Nov 16 '15 at 09:52
  • The main reason I'm looking for an alternative, besides maybe getting rid of the ~150 lines of code that I have right now, is learning purposes. It doesn't have anything to do with performance. – Wilsu Nov 16 '15 at 09:58
  • MyCharacter is an object that gets created and returned inside/by the method whenever it's called. The returned object is then written into a `List`. I just don't want string parsing to be a part of the Character class (for example in the constructor or something), since it should only store it's stats. – Wilsu Nov 16 '15 at 10:02

4 Answers4

7

Since you know the exact format, you can just access the indexes directly:

string stats = "Health: 100 Mana: 100 MoveSpeed: 100";

var statsArray = stats.Split(' ');
MyCharacter.Health = statsArray[1];
MyCharacter.Mana = statsArray[3];
MyCharacter.MoveSpeed = statsArray[5];

You could also use a regular expression for this, which has the benefit that it further validates your pattern (so if there is a case that does not match your format, you get an exception):

var m = Regex.Match(stats, @"Health: (\d+) Mana: (\d+) MoveSpeed: (\d+)");

MyCharacter.Health = m.Groups[1].Value;
MyCharacter.Mana = m.Groups[2].Value;
MyCharacter.MoveSpeed = m.Groups[3].Value;

Note: You probably want those properties to contain integers so you can calculate with the values, so you should call int.Parse() on each of the values.

poke
  • 369,085
  • 72
  • 557
  • 602
  • I used the last day to get into regular expressions and damn, this is absolutely perfect, thanks, man :) – Wilsu Nov 17 '15 at 09:19
1

You can use dictionary. It will be very easy and simple.

Dictionary<string, int> dictionary =new Dictionary<string, int>();
dictionary.Add("health",100);
dictionary.Add("mana",100);
dictionary.Add("speed",40);

then

mycharacter.Health=dictionary["health"];
mycharacter.Health=dictionary["mana"];
mycharacter.Health=dictionary["speed"];
Burak Karasoy
  • 1,682
  • 2
  • 21
  • 33
0

You can, just put a space, or any given character as a separator, in between the values. If the order is always the same you won't have problems. If you are reading the string from file, writing characters i fare more inefficient than writing the data in binary as a raw file composed by floats. the file would be sizeof(float)*18. You choose the semantic of each value.

deight
  • 331
  • 1
  • 4
  • 15
0

Regular Expressions is the best way to parse the string.

Check this:

public class Character
{
    public int Health;
    public int Mana;
    public int MoveSpeed;

    public static Character FromString(string characterData)
    {
        MatchCollection matches = Regex.Matches(characterData, "[A-Za-z]+: ([\\d]+)");
        Character myCharacter = new Character();
        myCharacter.Health = Convert.ToInt32(matches[0].Groups[1].Value);
        myCharacter.Mana = Convert.ToInt32(matches[1].Groups[1].Value);
        myCharacter.MoveSpeed = Convert.ToInt32(matches[2].Groups[1].Value);
        return myCharacter;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        Character myCharacter = Character.FromString("Health: 100 Mana: 110 MoveSpeed: 120");
    }
}
Oguz Ozgul
  • 6,809
  • 1
  • 14
  • 26