将字符串转换为Dictionary<string, string>的Linq方法

6
我正在使用一个字典来保存一些参数,但我发现无法序列化实现IDictionary接口的任何内容(无法序列化IDictionary)。
为了解决这个问题,我想将字典转换为字符串进行序列化,然后在需要时再转换回字典。
由于我正在尝试改善我的LINQ,所以这似乎是一个好地方,但我不确定该如何开始。
以下是没有使用LINQ实现的示例:
/// <summary>
/// Get / Set the extended properties of the FTPS processor
/// </summary>
/// <remarks>Can't serialize the Dictionary object so convert to a string (http://msdn.microsoft.com/en-us/library/ms950721.aspx)</remarks>
public Dictionary<string, string> FtpsExtendedProperties
{
    get 
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();

        // Get the Key value pairs from the string
        string[] kvpArray = m_FtpsExtendedProperties.Split('|');

        foreach (string kvp in kvpArray)
        {
            // Seperate the key and value to build the dictionary
            string[] pair = kvp.Split(',');
            dict.Add(pair[0], pair[1]);
        }

        return dict; 
    }

    set 
    {
        string newProperties = string.Empty;

        // Iterate through the dictionary converting the value pairs into a string
        foreach (KeyValuePair<string,string> kvp in value)
        {
            newProperties += string.Format("{0},{1}|", kvp.Key, kvp.Value);    
        }

        // Remove the last pipe serperator
        newProperties = newProperties.Substring(0, newProperties.Length - 1);
    }
}

顺便提一下,你可以使用'Linq'来生成字符串:string.Join("|", value.Select(kvp => string.Format("{0},{1}", kvp.Key, kvp.Value)))(但在.NET 3.5中,你需要在Select()上加上.ToArray())。 - Andras Zoltan
6个回答

11

试试这样做:

var dict = str.Split(';')
              .Select(s => s.Split(':'))
              .ToDictionary(a => a[0].Trim(), a => a[1].Trim()));

对于以下类型的字符串,上述内容是正确的

"mykey1:myvalue1; mykey2:value2;...."

@Andras Zoltan - 实际上,我不知道“op string”,这就是为什么我用示例字符串发布了我的答案。 - Pranay Rana

3
在您的代码环境中
/// Get / Set the extended properties of the FTPS processor
/// </summary>
/// <remarks>Can't serialize the Dictionary object so convert to a string (http://msdn.microsoft.com/en-us/library/ms950721.aspx)</remarks>
public Dictionary<string, string> FtpsExtendedProperties
{
get 
{

Dictionary<string, string> dict = m_FtpsExtendedProperties.Split('|')
      .Select(s => s.Split(','))
      .ToDictionary(key => key[0].Trim(), value => value[1].Trim());

    return dict; 
}

set 
{

        // NOTE: for large dictionaries, this can use
        // a StringBuilder instead of a string for cumulativeText

        // does not preserve Dictionary order (if that is important - reorder the String.Format)
    string newProperties = 
              value.Aggregate ("",
                      (cumulativeText,kvp) => String.Format("{0},{1}|{2}", kvp.Key, kvp.Value, cumulativeText));

        // Remove the last pipe serperator
        newProperties = newProperties.Substring(0, newProperties.Length - 1);

        }
    }

我没有测试过这个,但是使用的函数应该可以给你一些关于如何用LINQ简洁地完成它的想法。


字典对象没有聚合方法。我自己一直在尝试这种方法,但运气不太好。 - TeamWild
@TeamWild,你在类文件的顶部添加了 "using System.Linq;" 吗? - Neil Fenwick
很好的get访问器方法。我喜欢你将键和值分开以便可以应用其他处理(如trim)的方式。 - TeamWild

3
另一个选择是使用linq-to-xml来处理繁重的工作,以确保一切都被正确解析。
开始于:
var dict = new Dictionary<string, string>()
{
    { "A", "a" },
    { "B", "b" },
    { "C", "c" },
};

您可以通过以下方式将其转换为 XML:

var xe = new XElement("d",
    from kvp in dict
    select new XElement("p",
        new XAttribute("k", kvp.Key),
        new XAttribute("v", kvp.Value))).ToString();

这将变成:

<d>
  <p k="A" v="a" />
  <p k="B" v="b" />
  <p k="C" v="c" />
</d>

要将其转换回字典,请使用以下方法:

var dict2 = XDocument
    .Parse(xml)
    .Root
    .Elements("p")
    .ToDictionary(
        x => x.Attribute("k").Value,
        x => x.Attribute("v").Value);

简单易懂,是吧?

使用这种方法可以避免需要专门转义特殊字符,比如"|"或";"。


这是一种有趣的方法,可以允许字典对进行序列化。对于我当前的问题来说,它似乎有点过重,但我会记住它,以备将来之需。谢谢。 - TeamWild
@TeamWild - 请记住,任何使用拆分、连接、解析等方法的方法,如果您在字符串中包含特殊字符,都是有风险的。使用linq-to-xml可以消除这种风险,并且即使对于相当大的字典也非常快速和高效。 - Enigmativity

1

请尝试以下代码

string vals = "a|b|c|d|e";
var dict = vals.Split('|').ToDictionary(x=>x);

dict 会给你一个包含五个条目的字典。


1
为了让您学习LINQ,我也包含了序列化。
var serialized = string.Join("|",from pair in value
                                 select string.Format("{0},{1}", pair.Key, pair.Value);

var deserialized = new Dictionary<string,string(
                       from pair in serialized.Split("|")
                       let tokens = pair.Split(",")
                       select new KeyValuePair<string,string>(tokens[0],tokens[1]));

0

一种选择是执行以下操作:

  1. '将'字典转换为NameValueCollection
  2. 使用以下代码将NameValueCollection转换为HttpValueCollection

    var parserCollection = HttpUtility.ParseQueryString(string.Empty); parserCollection.Add(yourNameValueCollection);

  3. parserCollection.ToString()将生成一个(url编码的)字符串版本的字典。

要将字符串形式转换回NameValueCollection,请使用HttpUtility.ParseQueryString(stringFormOfYourDictionary)。然后执行步骤1的反向操作,将NameValueCollection转换回字典。

这样做的优点是,它将在不考虑字典内容的情况下工作。不依赖于数据格式(因此无论字典中键或值的值如何,都可以正常工作)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接