Linq для преобразования строки в словарь <строка, строка> - PullRequest
5 голосов
/ 05 сентября 2011

Я использую словарь для хранения некоторых параметров, и я только что обнаружил, что невозможно сериализовать что-либо, что реализует 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);
    }
}

Ответы [ 6 ]

10 голосов
/ 05 сентября 2011

попробуйте что-то вроде этого

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

выше единицы верно для следующих типов строк

"mykey1:myvalue1; mykey2:value2;...."
3 голосов
/ 05 сентября 2011

В контексте вашего кода

/// 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

2 голосов
/ 05 сентября 2011

Другой вариант - использовать 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);

Легко, да?

Этот метод избавит от необходимости специально экранировать специальные символы, такие как «|»или ";".

1 голос
/ 05 сентября 2011

Для того, чтобы вы изучали 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]));
1 голос
/ 05 сентября 2011

Попробуйте следующий код

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

dict даст вам словарь, содержащий пять записей.

0 голосов
/ 10 ноября 2011

Можно выбрать один из следующих вариантов:

  1. «Преобразовать» словарь в коллекцию NameValueCollection
  2. Использовать приведенный ниже код для преобразовать NameValueCollection в HttpValueCollection .

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

  3. parserCollection.ToString () затем сгенерирует (закодированную в URL) строковую версию вашего словаря.

Для преобразования строковой формы обратнодля NameValueCollection используйте HttpUtility.ParseQueryString (stringFormOfYourDictionary).Затем выполните обратное действие шага 1, чтобы преобразовать NameValueCollection обратно в словарь.

Преимущество этого состоит в том, что он будет работать независимо от содержимого словаря.Нет никакой зависимости от формата данных (поэтому он будет работать нормально независимо от значений ключей или значений в словаре).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...