从分隔字符串</string,string>填充Dictionary <string,string>的最“优雅”方式

时间:2012-01-26 15:23:06

标签: c# string dictionary split

我认为那些对基本字符串操作,循环和字典有轻微把握的人可以解决如何从字符串填充字典,如下所示:

黑色:#00000 |绿色:#008000 | (其中“黑色”是键,“#000000”是值)

但在你看来,最优雅的做法是什么?我可以使用哪种最有效/更简洁的编码来实现它?到目前为止,我有:

    public static Dictionary<String, String> ThemeColors
    {
        get
        {
            Dictionary<String, String> themeColors = new Dictionary<string, string>();
            foreach (String colorAndCode in GetSettingByName("ThemeColors").ToString().Split('|'))
            {
                themeColors.Add(colorAndCode.Split(':').First(), colorAndCode.Split(':').Last());
            }
            return themeColors;
        }
    }

GetSettingByName(“ThemeColours”)返回上面的字符串(以粗体显示)。

它的功能很明显,一切正常,但我想确保我现在开始思考这个并制定最好的做事方式,而不仅仅是让它发挥作用。

我可以在Dictionary循环上使用yield吗?例如??

4 个答案:

答案 0 :(得分:8)

 public static Dictionary<String, String> ThemeColors
    {
        get
        {
           return GetSettingByName("ThemeColors").ToString().Split('|').ToDictionary(colorAndCode => colorAndCode.Split(':').First(), colorAndCode => colorAndCode.Split(':').Last());
        }
    }

正如评论中建议的更优雅的方式

 public static Dictionary<String, String> ThemeColors2
        {
            get
            {
                return GetSettingByName("ThemeColors").ToString().Split('|').Select(x => x.Split(new[] { ':' }, 2)).ToDictionary(x => x[0], x => x[1]);
            }
        }

答案 1 :(得分:4)

我实际上最喜欢你的方法的一个轻微变体:

    public static Dictionary<String, String> ThemeColors
    {
        get
        {
            Dictionary<String, String> themeColors = new Dictionary<string, string>();
            foreach (String colorAndCode in GetSettingByName("ThemeColors").ToString().Split('|'))
            {
                var parts = colorAndCode.Split(':');
                themeColors.Add(parts[0], parts[1]);
            }
            return themeColors;
        }
    }

唯一的区别是第二个Split()只执行一次,而直接索引则不是First()Last()

现在ToDictionary()很有意义,在更广泛的查询中包含某些内容是有道理的,我当然不会认为它错了,但这并不像你的方法特别冗长或任何东西。

但是我喜欢改变容忍重复的方法很容易(使用dict[parts[0]] = parts[1]并且它会覆盖重复而不是抛出),但是也很容易改为抛出Black:#00000:#010101通过测试parts的大小。

在另一个方向,如果你需要尽可能快地解析一个庞大的字符串,那么就把优雅抛出窗口并用一些东西替换它,然后通过|字符串进行扫描。而不是使用Split()

与此同时,上述内容在简洁和精确之间形成了良好的中间地带。

答案 2 :(得分:3)

这是一个使用foreach的替代方案。 @Haris Hasan和@vcsjones的答案本身就很优雅。我展示这个的原因是我将这个逻辑封装在一个静态StringHelper类中,然后这个方法可以用作string的扩展。

上述任何一个答案的代码都可以纳入此方法。

调用示例:

var str = "Black:#00000|Green:#008000|";
Dictionary<string, string> dict = str.NameValuePairsToDictionary(":", "|");


    /// <summary>
    /// convert a string that consists of Name/Value Pairs to a Dictionary.
    /// Name and Value are separated by a given name/value separator
    /// Pairs are separated by a given pair separator token.
    /// example:
    /// Black:#00000|Green:#008000
    /// </summary>
    /// <param name="nvParis">string of name value pairs</param>
    /// <param name="nvSeparator">string that separates the name and value in a name value pair</param>
    /// <param name="pairSeparator">string that separates the name/value pairs from each other</param>
    /// <returns>Dictionary of Name value pairs as string,string</returns>
public static class StringHelper
{
    public static Dictionary<string, string> NameValuePairsToDictionary(this string nvPairs, string nvSeparator, string pairSeparator)
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();

        // default - "\n\r"
        // split name value pairs by separator
        string[] items = nvPairs.Split(pairSeparator.ToCharArray());

        // for each split item, split the name/value pair by 
        // pair separator to add a dictionary item
        foreach (string item in items)
        {
            string[] keyVal = item.Split(nvSeparator.ToCharArray());
            if (keyVal.Length > 1)
                dict.Add(keyVal[0], keyVal[1]);
        }

        return dict;
    }
}

答案 3 :(得分:1)

object settings = "Black:#00000|Green:#008000|";

var themeColors = (from setting in ((string)settings).Split('|')
                   where setting != ""
                   select setting.Split(new[]{':'}, 2))
                  .ToDictionary(a => a[0], a => a[1]);