【问题标题】:Linq to convert a string to a Dictionary<string,string>Linq 将字符串转换为 Dictionary<string,string>
【发布时间】:2011-09-05 10:29:40
【问题描述】:

我正在使用字典来保存一些参数,但我刚刚发现无法序列化任何实现 IDictionary (unable to serialize 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 =&gt; string.Format("{0},{1}", kvp.Key, kvp.Value)))(但在 .Net 3.5 中,您需要在 Select() 上添加一个 .ToArray()

标签: c# linq dictionary


【解决方案1】:

试试这样的

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

对于以下类型的字符串,以上一个是正确的

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

【讨论】:

  • @Andras Zoltan - 实际上我不知道我用示例字符串发布我的答案的操作字符串
【解决方案2】:

在您的代码上下文中

/// 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 相当简洁地完成此操作

【讨论】:

  • Dictionary 对象没有 Aggregate 方法。我自己一直在尝试这种方法,但运气不佳。
  • @TeamWild,您是否添加了“使用 System.Linq;”到你的类文件的顶部?
  • 获取访问器的好方法。我喜欢您将键和值分开的方式,以便可以应用额外的处理(修剪)。
【解决方案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 - 请记住,如果您在字符串中包含特殊字符,任何使用拆分、连接、解析等的方法都是有风险的。使用 linq-to-xml 消除了这种风险,即使是非常大的字典也非常快速且非常有效。
【解决方案4】:

试试下面的代码

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

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

【讨论】:

    【解决方案5】:

    为了您学习 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]));
    

    【讨论】:

      【解决方案6】:

      一种选择是:

      1. 'Convert' the Dictionary to a NameValueCollection
      2. 使用下面的代码convert the NameValueCollection into a HttpValueCollection

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

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

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

      这样做的好处是无论字典的内容如何,​​它都可以工作。不依赖于数据的格式(因此无论字典中的键或值的值如何,它都可以正常工作)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-01
        • 1970-01-01
        • 2010-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        相关资源
        最近更新 更多