C# - 寻找一种简单的方法来解析两个不同表示之间的字符串值(数字和英语)

问题描述 投票:4回答:6

我正在开发一个小帮手应用程序,并想知道是否有更好的方法来完成这一件事 -

我有一个CSV文件,我正在读取我的程序,我正在解析每行中的一个值,从一个数值(总是一个整数,在1到5之间)到一个字符串值,以便在程序中更容易表示。当我保存文件时,我需要从字符串表示转换回数字表示。目前,我通过switch语句执行此操作,但我知道必须有一种更简洁的方法来实现此目的。

我目前使用的函数有两个参数。其中一个参数是一个字符串,可以是我试图解析的那个值的数字表示或字符串表示,另一个值是一个布尔值,告诉函数它应该转换第一个参数的方式。如果boolean参数为true,则转换为数字表示形式,如果为false,则转换为字符串表示形式。这是我解析值的函数:

string ParseRarity(string rarity, bool toNumericalStr)
{
    if (toNumericalStr)
    {
        switch (rarity)
        {
            case "Very Common":
                return "1";
            case "Common":
                return "2";
            case "Standard":
                return "3";
            case "Rare":
                return "4";
            case "Very Rare":
                return "5";
        }
    }
    else
    {
        switch (rarity)
        {
            case "1":
                return "Very Common";
            case "2":
                return "Common";
            case "3":
                return "Standard";
            case "4":
                return "Rare";
            case "5":
                return "Very Rare";
        }
    }

    return "";
}

任何缩短此代码的帮助将不胜感激,所以“谢谢”提前!

c# string parsing switch-statement
6个回答
1
投票

我也会给你一个答案,你可以创建一个包含稀有值的静态“存储库”类。下划线存储机制是Dictionary<int, string>。这将强制你所有的稀有物具有一个唯一的密钥(int),并且通过该密钥可以快速访问。

public static class RarityRepository
{
    private static Dictionary<int, string> _values = new Dictionary<int, string>()
    {  
        { 1, "Very Common" },
        { 2, "Common" },
        { 3, "Standard" },
        { 4, "Rare" },
        { 5, "Very Rare" },
    };

    public static string GetStringValue(int input)
    { 
        string output = string.Empty;  // returns empty string if no matches are found
        _values.TryGetValue(input, out output);
        return output;
    }

    public static int GetIntValue(string input)
    {
        var result = _values.FirstOrDefault(x => string.Compare(x.Value, input, true) == 0);
        if (result.Equals(default(KeyValuePair<int,string>)))
        {
            return -1; // returns -1 if no matches are found
        }
        return result.Key;
    }
}

我做了一个小提琴here,感谢@Ron寻找我的午夜脑代码缺陷!


1
投票

如果你想简单的污垢,只需编写一个像这样的静态助手类:

public class CodeConverter
{
    private static readonly string[] lookup = new []
    {
        "[Unknown]",
        "Very Common",
        "Common",
        "Standard",
        "Rare",
        "Very Rare"
    };

    public static string CodeToString(int code)
    {
        if (code < 0 || code > lookup.GetUpperBound(0)) code = 0;
        return lookup[code];
    }

    public static int StringToCode(string text)
    {
        int i = Array.IndexOf(lookup, text);
        return Math.Min(0,i);
    }
}

0
投票

你可以做一些非常简单的事情,但你应该把它分成两种方法。有一种做两件事的方法是非常糟糕的架构。

public static class RarityConverter
{
    private static List<Tuple<int, string>> Rarities = new List<Tuple<int, string>>()
    {
        new Tuple<int, string>(1, "Very Common"),
        new Tuple<int, string>(2, "Common"),
        new Tuple<int, string>(3, "Standard"),
        new Tuple<int, string>(4, "Rare"),
        new Tuple<int, string>(5, "Very Rare"),
    };

    public static string ToString(int rarity)
    {
        return Rarities.FirstOrDefault(t => t.Item1 == rarity)?.Item2;
    }

    public static int? ToInt(string rarity)
    {
        return Rarities.FirstOrDefault(t => string.Compare(t.Item2, rarity, true) == 0)?.Item1;
    }
}

您也可以使用Enum,但这需要您使用DescriptionAttribute来装饰/转换传入的字符串名称到枚举名称。


0
投票

我将创建一个可以存储两个值的类,然后根据需要调用每个值。

public class Rarity
{
    public Rarity(int numValue)
    {
        NumValue = numValue;

        switch(numValue)
        {
            case 1:
                StringValue = "Very Common";
                break;
            case 2:
                StringValue = "Common";
                break;
            case 3:
                StringValue = "Standard";
                break;
            case 4:
                StringValue = "Rare";
                break;
            case 5:
                StringValue = "Very Rare";
                break;
            default:
                StringValue = "";
                break;
        }
    }
    public int NumValue { get; }
    public string StringValue { get; }
}

在加载CSV值时,可以使用您提到的int值初始化类对象(在我的示例中为Rarity)。

Rarity rarity = new Rarity(my_csv_int_value);

现在,您可以随时获取所需的价值。

rarity.NumValue //1,2,3,4,5
rarity.StringValue //Very Common, Common, etc...

可能大约相同数量的代码,但更通用,你不必继续解析字符串。


0
投票

我建议

enum,即使有额外的装饰需求。对我来说唯一的另一个竞争力是数据应该存在于数据域中,而不是代码域中,所以我很可能在代码中没有明确地显示这些值!

我不推荐这种确切的方法或OP的方法,我回答了简洁的需要

你的逻辑已经在字符串到字符串转换的土地上。为什么不O(1)双向查找?你可以有一个双向查找/字典。

var lookup = new Dictionary<string, string>()
{  
    { ”1”, "Very Common" },
    { “2”,  "Common" },
    { “3”, "Standard" },
    { “4,” "Rare" },
    { “5”, "Very Rare" },
    { “Very Common”, “1” }
    //etc iPhone editing sucks
};

您甚至可以只写出Dictionary的正向查找一半,并在反向查找部分中使用扩展方法或专用类ToTwoWayLookup填充,而不必键入2x值。 (有关方法,请参阅how to do a dictionary reverse lookup的接受答案),您也可以删除ContainsKey检查

然后在你的函数中你摆脱了bool参数,只是在这个字典中查找。我不知道函数名是什么... FlipRepresentation?

我可能会这样做

也许单独使用reverseLookup字典会更有意义,因此您可以使用两个具有更有意义名称的方法。 Terseness并非全部!努力使代码可以被其他人理解!我更喜欢读ToNumerical(“Common”),ToNumberFromRarityName,ToRarityName(“1”)或ToRarityNameFromNumber而不是FlipRepresentation('1“)或ParseRarity(”1“,false);

我可能不会留下字符串< - >字符串为字符串< - > int land,就像其他建议在从文件读取时保存对int.Parse(val)的调用。


0
投票

这似乎是这个值的标准,如果是我,我会简化这个(根据要求,我会添加范围检查或错误处理)。

public static class Rarities
{
    private static List<string> _rarityValues = new List<string>()
    {
        "Empty",
        "Very Common",
        "Common",
        "Standard",
        "Rare",
        "Very Rare"
    };

    public static string ToRarityString(this int rarity)
    {
        return _rarityValues[rarity];
    }

    public static int ToRairityInt(this string rarity)
    {
        return _rarityValues.IndexOf(rarity);
    }
}

然后你可以直接从值调用:

   var rarityInt = 1;
   var rarityString = "Rare";

   var stringValue = rarityInt.ToRarityString();
   var intValue = rarityString.ToRairityInt();
© www.soinside.com 2019 - 2024. All rights reserved.