字典,多维或锯齿状数组

时间:2015-06-10 20:35:26

标签: c# arrays dictionary

我有这个字符串:

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 个答案:

答案 0 :(得分:1)

我认为Dictionary<string, Dictionary<string, List<int>>>是一个很好的结构来存储这些信息。

外部词典的关键是&#34; {#}&#34;

的值

内部词典的关键是&#34; [#]&#34;

的值

List内部Dictionary中的值将是&#34;(#)&#34;的值,但没有括号

为了解析这些信息,我认为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

答案 1 :(得分: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. 对于每个符号,请采取适当的措施。

  6. 巨大注意:此代码强烈期望输入字符串格式正确。例如,如果您传入字符串"{1}(17)",一切都会爆炸,因为没有中间[56]来填充leaves变量new List<int> ( {{1}}代码期望已经实例化。