2015-06-10 3 views
-3

У меня есть эта строка:словарь, многомерный или неровный массив

string Text = "{1}[56](17)(20)(13)(14)[895](11)(20)[3](8)(12)(3)[19](1)(2)(13)(7)(6)"; 

и я должен вернуть это:

Array ( [Type] => 1 
      [Items] => Array ([56] => Array ( [1] => 17 
               [2] => 20 
               [3] => 13 
               [4] => 14) 
           [895] => Array ( [1] => 11 
                [2] => 20) 
           [3] => Array ( [1] => 8 
               [2] => 12 
               [3] => 3) 
           [19] => Array ( [1] => 1 
               [2] => 2 
               [3] => 13 
               [4] => 7 
               [5] => 6) 
           ) 
     ) 

Как я могу это сделать? Я преуспел в php, но в C# я не могу найти решение. Я пробовал сначала со словарем, но я просто не могу его достичь. Я просто не знаю, как сделать словарь с ключом с несколькими значениями, также имеющими несколько значений. До сих пор я сделал это:

var Menu_Matrix = new Dictionary<string, string>(); 
    var Menu_Items = new Dictionary<string, List<string>>(); 
    char[] sep1 = { '{', '}' }; 
    char[] sep2 = { '[', ']' }; 
    char[] sep3 = { '(', ')' }; 
    string[] Menu_Id = new string [10]; 
    string[] Category_Id = new string[20]; 
    Menu_Id = Text.Split(sep1); 
    Menu_Matrix.Add("Type", Menu_Id[1]); 
    Category_Id = Menu_Id[2].Split(sep2); 
    int cat_len = 0; 
    cat_len = Category_Id.Length; 
    for (int i = 1; i < cat_len;i++) 
    { int pos = 0; 
     if(Category_Id[i+1].IndexOf('(')!=-1) 
     pos=i+1; 
     if(pos>i) 
     { var item = new List<string>(); 
      string[] Item_id = new string[20]; 
      Item_id = Category_Id[pos].Split(sep3); 
      for (int j = 1; j < Item_id.Length;j++) 
      if(Item_id[j]!="") 
       item.Add(Item_id[j]); 
      Menu_Items.Add(Category_Id[i], item); 
     } 
    i = pos; 
     } 
    } 
    return Menu_Items; 

и результат:

       [56] => Array ([1] => 17 
              [2] => 20 
              [3] => 13 
              [4] => 14) 
          [895] => Array ([1] => 11 
               [2] => 20) 
           [3] => Array ([1] => 8 
               [2] => 12 
               [3] => 3) 
           [19] => Array ([1] => 1 
               [2] => 2 
               [3] => 13 
               [4] => 7 
               [5] => 6) 

Надеется, что вы знаете, что я хочу сказать, и помогите мне, пожалуйста! Меня не волнует, что я использую: словарь, зубчатый массив или многомерный массив.

+2

Вы сказали, что вы пытались что-то в PHP, может показать нам, что таким образом мы можем помочь вы с ним? – castis

+0

Чтобы использовать несколько значений одного и того же ключа в словаре, используйте словарь > – deathismyfriend

+0

Можете ли вы поделиться тем, что вы хотите, чтобы конечный результат выглядел? – whihathac

ответ

1

Я думал, что Dictionary<string, Dictionary<string, List<int>>> будет хорошей структурой для его хранения.

Ключ к внешнему словарю бы значение «{#}»

Ключ к внутреннему словарю был бы значение «[#]»

Значения в List, во внутреннем Dictionary, было бы значение «(#)», но без скобок

чтобы разобрать эту информацию, я думал комбинации Regex.Split с, чтобы получить внешние и внутренние ключи вместе с Regex.Match, чтобы получить значения внутренних клавиш были хорошим подходом.

Пример кода:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text.RegularExpressions; 

public class Program 
{ 
    public static void Main() 
    { 
     string Text = "{1}[56](17)(20)(13)(14)[895](11)(20)[3](8)(12)(3)[19](1)(2)(13)(7)(6){2}[99](1)(2)(3)"; 

     // Split out pairs 
     // 0: {#} 
     // 1: [#](#)..(n) 
     string[] splits = Regex.Split(Text, "({\\d+})").Where(split => !String.IsNullOrEmpty(split)).ToArray(); 
     Dictionary<string, Dictionary<string, List<int>>> items = new Dictionary<string, Dictionary<string, List<int>>>(); 
     for (int i = 0; i < splits.Length; i += 2) 
     { 
      // splits[i] is {#} which will make the key for this part of the Dictionary 
      items.Add(splits[i], new Dictionary<string, List<int>>()); 
      items[splits[i]] = new Dictionary<string, List<int>>(); 

      // Split out sub pairs 
      // 0: [#] 
      // 1: (#)..(n) 
      string[] subSplits = Regex.Split(splits[i + 1], "(\\[\\d+\\])").Where(subSplit => !String.IsNullOrEmpty(subSplit)).ToArray(); 
      for (int j = 0; j < subSplits.Length; j += 2) 
      { 
       // subSplits[j] is [#] which will make the key for the inner Dictionary 
       items[splits[i]].Add(subSplits[j], new List<int>()); 

       // subSplits[j + 1] is all of the (#) for each [#] 
       // which we'll add to the List of the inner Dictionary 
       Match m = Regex.Match(subSplits[j + 1], "(\\d+)"); 
       while (m.Success) 
       { 
        items[splits[i]][subSplits[j]].Add(Convert.ToInt32(m.Groups[0].ToString())); 
        m = m.NextMatch(); 
       } 
      } 
     } 

     // Print the keys of the Dictionary, the keys of the inner Dictionary, the values of the inner Dictionary 
     foreach (string key in items.Keys) 
     { 
      Console.WriteLine("Key: {0}", key); 
      foreach (string subKey in items[key].Keys) 
      { 
       Console.WriteLine("\t SubKey: {0}", subKey); 
       Console.WriteLine("\t\t Value: {0}", String.Join(", ", items[key][subKey])); 
      } 
     } 
    } 
} 

Результаты:

Key: {1} 
    SubKey: [56] 
     Value: 17, 20, 13, 14 
    SubKey: [895] 
     Value: 11, 20 
    SubKey: [3] 
     Value: 8, 12, 3 
    SubKey: [19] 
     Value: 1, 2, 13, 7, 6 
Key: {2} 
    SubKey: [99] 
     Value: 1, 2, 3 

Посмотреть рабочий образец здесь ... https://dotnetfiddle.net/Zt5gXc

+0

Спасибо за ваш ответ! Ваше решение работает хорошо, но оно не обрабатывает исключения. Я не знаю, почему я не думал о словаре в словаре. Поэтому я изменил свой код с вашей идеей, и он работает !!! Еще раз спасибо. –

+0

@NicoletaSerban С какими исключениями вы хотите справиться? Любой алгоритм синтаксического анализа будет полагаться на то, что данные находятся в правильном формате. – Shar1er80

+0

@NicoletaSerban Вы упомянули, что ваш код работает, если вы нашли мой ответ полезным для вашей проблемы, любезно нажмите галочку на мой ответ, чтобы решить вопрос :-) – Shar1er80

0

Вы могли бы рассмотреть что-то вроде этого:

string text = "{1}[56](17)(20)(13)(14)[895](11)(20)[3](8)(12)(3)[19](1)(2)(13)(7)(6)"; 
string[] tokens = text.Split(new Char[] { '}', ']', ')' }); 

char symbol; 
int value; 

Dictionary<int, Dictionary<int, List<int>>> data = new Dictionary<int, Dictionary<int, List<int>>>(); 
Dictionary<int, List<int>> items = null; 
List<int> leaves = null; 

foreach (string token in tokens) { 
    if (token.Length == 0) break; 
    symbol = token[0]; 
    value = Int32.Parse(token.Substring(1)); 
    switch (symbol) { 
    case '{': 
    items = new Dictionary<int, List<int>>(); 
    data.Add(value, items); 
    break; 
    case '[': 
    leaves = new List<int>(); 
    items.Add(value, leaves); 
    break; 
    case '(': 
    leaves.Add(value); 
    break; 
    } 
} 

foreach (int type in data.Keys) 
{ 
    Console.WriteLine("Type => {{{0}}}", type); 
    Console.WriteLine("\tItems =>"); 
    items = data[type]; 
     foreach (int item in items.Keys) 
     { 
     Console.WriteLine("\t\t[{0}] =>", item); 
     leaves = items[item]; 
     for (int i = 0; i < leaves.Count; i += 1) { 
     Console.WriteLine("\t\t\t[{0}] => ({1})", i, leaves[i]); 
     } 
    } 
} 

See this working at DotNetFiddle.net

Это производит вывод:

Type => {1} 
    Items => 
     [56] => 
      [0] => (17) 
      [1] => (20) 
      [2] => (13) 
      [3] => (14) 
     [895] => 
      [0] => (11) 
      [1] => (20) 
     [3] => 
      [0] => (8) 
      [1] => (12) 
      [2] => (3) 
     [19] => 
      [0] => (1) 
      [1] => (2) 
      [2] => (13) 
      [3] => (7) 
      [4] => (6) 

Вот выбега, как это работает:

  1. Разделите все цифры на знаке закрытия (фигурная скобка, квадратная скобка или скобки). Это создает массив, такой как { "{1", "[56", "(17", ... "(6", "" }.

  2. Создайте переменную для каждого уровня структур данных, которая представляет последний объект на этой глубине иерархии.

  3. Завершите работу, если мы находимся на последнем, пустое, знаковое.

  4. Истерируйте с помощью вырезающих токенов и сохраните открытую метку, которая представляет уровень иерархии структуры данных, в symbol, а численное значение - value.

  5. Для каждого символа предпримите соответствующие действия.

Огромное Примечание: этот код сильно ожидает входной строки, чтобы быть хорошо сформировано. Если, например, вы прошли в строке "{1}(17)", все бы взорвалось, потому что не было промежуточного [56], чтобы заполнить переменную leaves с помощью new List<int>, что код ( ожидает, что он будет создан.

+0

Благодарим вас за ответ. –

Смежные вопросы