C# 如何改进将点分隔字符串转换为数据对象的算法?

C# 如何改进将点分隔字符串转换为数据对象的算法?,c#,algorithm,C#,Algorithm,我目前正在研究一种算法,将点分隔字符串(Tag1.Tag2.Foo)转换为将在树状视图组件中使用的数据对象。对于字符串的每个部分,如果没有对象,则将创建一个对象。另外,这些对象将与父id“链接在一起”,以便最终数据将显示为树 原始数据: “Tag1.Tag2.Foo”、“Tag1.Tag2.Bar”、“Tag2.Tag3.FooBar”、“Tag3” 转化为: [ { "Id": "ac96e451-b4e4-47f7-afd2-0673b28128d8", "ParentI

我目前正在研究一种算法,将点分隔字符串(Tag1.Tag2.Foo)转换为将在树状视图组件中使用的数据对象。对于字符串的每个部分,如果没有对象,则将创建一个对象。另外,这些对象将与父id“链接在一起”,以便最终数据将显示为树

原始数据:

“Tag1.Tag2.Foo”、“Tag1.Tag2.Bar”、“Tag2.Tag3.FooBar”、“Tag3”

转化为:

[
  {
    "Id": "ac96e451-b4e4-47f7-afd2-0673b28128d8",
    "ParentId": "00000000-0000-0000-0000-000000000000",
    "Identifier": "Tag1",
    "Text": "Tag1"
  },
  {
    "Id": "e9a86afe-7af5-41e8-a791-11f50a6d472b",
    "ParentId": "ac96e451-b4e4-47f7-afd2-0673b28128d8",
    "Identifier": "Tag1.Tag2",
    "Text": "Tag2"
  },
  {
    "Id": "089403ee-193a-4992-96b7-d69ef9fff957",
    "ParentId": "e9a86afe-7af5-41e8-a791-11f50a6d472b",
    "Identifier": "Tag1.Tag2.Foo",
    "Text": "Foo"
  },
  {
    "Id": "4d806c52-153e-4752-bb9d-f2d187fb11e8",
    "ParentId": "e9a86afe-7af5-41e8-a791-11f50a6d472b",
    "Identifier": "Tag1.Tag2.Bar",
    "Text": "Bar"
  },
  {
    "Id": "c3e1da58-075a-4c8a-9381-316a7b609b87",
    "ParentId": "00000000-0000-0000-0000-000000000000",
    "Identifier": "Tag2",
    "Text": "Tag2"
  },
  {
    "Id": "359c40db-dc12-44e1-b055-d198b568070d",
    "ParentId": "c3e1da58-075a-4c8a-9381-316a7b609b87",
    "Identifier": "Tag2.Tag3",
    "Text": "Tag3"
  },
  {
    "Id": "75418314-bc2c-489f-9319-d57375d4cfec",
    "ParentId": "359c40db-dc12-44e1-b055-d198b568070d",
    "Identifier": "Tag2.Tag3.FooBar",
    "Text": "FooBar"
  },
  {
    "Id": "fd64fe19-7dae-4965-9688-720e7fc210b7",
    "ParentId": "00000000-0000-0000-0000-000000000000",
    "Identifier": "Tag3",
    "Text": "Tag3"
  }
]
在树状视图中查看:

  • Tag1
    • Tag2
      • 酒吧
  • Tag2
    • Tag3
      • FooBar
      • Tag3

      我当前的代码可以工作,但是对于大数据,它会变得很慢。在20-30秒内计算了12000个字符串。我认为还有改进的余地。我看了一下并行计算,但遇到了竞争条件问题和不断变化的输出集合问题。也许有人可以指出我可以改进代码的地方,或者指出如何处理此类问题的另一个方向

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using Newtonsoft.Json;
      namespace TreeBuilder
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var tags = new List<string> { "Tag1.Tag2.Foo", "Tag1.Tag2.Bar", "Tag2.Tag3.FooBar", "Tag3" };
      
                  var treeItems = new List<TreeItem>();
      
                  foreach (var tag in tags)
                  {
                      CreateTreeItems(tag, treeItems);
                  }
      
                  Console.WriteLine(JsonConvert.SerializeObject(treeItems, Formatting.Indented));
              }
      
              static void CreateTreeItems(string rawItem, List<TreeItem> treeItems)
              {
                  var rawItems = rawItem.Split('.');
      
                  for (int i = 0; i < rawItems.Length; i++)
                  {
                      var currentIdentifier = string.Join('.', rawItems.Take(i + 1).ToArray());
      
                      // create item if doesnt exist already
                      if (!treeItems.Any(ti => ti.Identifier == currentIdentifier))
                      {
                          var item = new TreeItem
                          {
                              Id = Guid.NewGuid(),
                              ParentId = Guid.Empty,
                              Text = rawItems[i],
                              Identifier = currentIdentifier
                          };
      
                          treeItems.Add(item);
      
                          // add as child, if necessary
                          var parentIdentifier = string.Join('.', currentIdentifier.Split('.')[0..(currentIdentifier.Split('.').Length - 1)]);
      
                          if (!string.IsNullOrEmpty(parentIdentifier))
                          {
                              item.ParentId = treeItems.FirstOrDefault(ti => ti.Identifier == parentIdentifier).Id;
                          }
                      }
                  }
              }
          }
      
          class TreeItem
          {
              public Guid Id { get; set; }
              public Guid ParentId { get; set; }
              public string Identifier { get; set; }
              public string Text { get; set; }
          }
      }
      
      
      使用系统;
      使用System.Collections.Generic;
      使用System.Linq;
      使用Newtonsoft.Json;
      命名空间树生成器
      {
      班级计划
      {
      静态void Main(字符串[]参数)
      {
      var tags=新列表{“Tag1.Tag2.Foo”、“Tag1.Tag2.Bar”、“Tag2.Tag3.FooBar”、“Tag3”};
      var treeItems=新列表();
      foreach(标签中的var标签)
      {
      CreateTreeItems(标记,treeItems);
      }
      WriteLine(JsonConvert.SerializeObject(treeItems,Formatting.Indented));
      }
      静态void CreateTreeItems(字符串rawItem、列表treeItems)
      {
      var rawItems=rawItem.Split('.');
      对于(int i=0;iti.Identifier==currentIdentifier))
      {
      变量项=新树项
      {
      Id=Guid.NewGuid(),
      ParentId=Guid.Empty,
      Text=原始项目[i],
      标识符=当前标识符
      };
      添加(项目);
      //如有必要,添加为子级
      var parentIdentifier=string.Join('.',currentIdentifier.Split('.')[0..(currentIdentifier.Split('.').Length-1)];
      如果(!string.IsNullOrEmpty(parentIdentifier))
      {
      item.ParentId=treeItems.FirstOrDefault(ti=>ti.Identifier==parentIdentifier.Id;
      }
      }
      }
      }
      }
      类树
      {
      公共Guid Id{get;set;}
      公共Guid ParentId{get;set;}
      公共字符串标识符{get;set;}
      公共字符串文本{get;set;}
      }
      }
      
      更新 添加了kalexis解决方案中提到的更改。我也删除了这个列表,因为它不再需要了。如果需要列表,可以对字典值使用.toList()

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using Newtonsoft.Json;
      namespace TreeBuilder
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var tags = new List<string> { "Tag1.Tag2.Foo", "Tag1.Tag2.Bar", "Tag2.Tag3.FooBar", "Tag3" };
      
                  var treeItems = new Dictionary<string, TreeItem>();
      
                  foreach (var tag in tags)
                  {
                      CreateTreeItems(tag, treeItems);
                  }
      
                  Console.WriteLine(JsonConvert.SerializeObject(treeItems, Formatting.Indented));
              }
      
              static void CreateTreeItems(string rawItem, List<TreeItem> treeItems)
              {
                  var rawItems = rawItem.Split('.');
      
                  for (int i = 0; i < rawItems.Length; i++)
                  {
                      var currentIdentifier = string.Join('.', rawItems.Take(i + 1).ToArray());
      
                      // create item if doesnt exist already
                      if (!treeItems.ContainsKey(currentIdentifier))
                      {
                          var item = new TreeItem
                          {
                              Id = Guid.NewGuid(),
                              ParentId = Guid.Empty,
                              Text = rawItems[i],
                              Identifier = currentIdentifier
                          };
      
                         treeItems[currentIdentifier] = item;
      
                          // add as child, if necessary
                          var parentIdentifier = string.Join('.', currentIdentifier.Split('.')[0..(currentIdentifier.Split('.').Length - 1)]);
      
                          if (!string.IsNullOrEmpty(parentIdentifier) 
                              && treeItems.TryGetValue(parentIdentifier, out var parent))
                          {
                              item.ParentId = parent.Id;
                          }
                      }
                  }
              }
          }
      
          class TreeItem
          {
              public Guid Id { get; set; }
              public Guid ParentId { get; set; }
              public string Identifier { get; set; }
              public string Text { get; set; }
          }
      }
      
      
      使用系统;
      使用System.Collections.Generic;
      使用System.Linq;
      使用Newtonsoft.Json;
      命名空间树生成器
      {
      班级计划
      {
      静态void Main(字符串[]参数)
      {
      var tags=新列表{“Tag1.Tag2.Foo”、“Tag1.Tag2.Bar”、“Tag2.Tag3.FooBar”、“Tag3”};
      var treeItems=新字典();
      foreach(标签中的var标签)
      {
      CreateTreeItems(标记,treeItems);
      }
      WriteLine(JsonConvert.SerializeObject(treeItems,Formatting.Indented));
      }
      静态void CreateTreeItems(字符串rawItem、列表treeItems)
      {
      var rawItems=rawItem.Split('.');
      对于(int i=0;i
      我相信这就是文化原则:

      • treeItems.Any(ti=>ti.Identifier==currentIdentifier)
      • treeItems.FirstOrDefault(ti=>ti.Identifier==parentIdentifier)
      这些迭代会遍历整个列表,它越大,所需的时间就越多。这就是每个标签!相反,尝试传递一个
      列表和一个
      字典,填充两者,并使用
      Dictionary.ContainsKey()
      检查标识符是否正确
      Original: 11908.4479ms
      With Dictionaries: 32.9763ms