【问题标题】:How do I create a concatenated list of string values based on list-style keys?如何根据列表样式的键创建串联的字符串值列表?
【发布时间】:2012-11-10 02:41:00
【问题描述】:

我有一本包含以下数据的字典:

Key    Value
1      Introduction
1.1    General
1.1.1  Scope
1.2    Expectations
2      Background
2.1    Early Development
...

我想做的是找出一种方法 - 在 C# 中 - 创建一个新列表(或附加到一个数组),其中的值基于列表样式键连接,如下所示:

Key    Value              Concatenation
1      Introduction       Introduction
1.1    General            Introduction - General
1.1.1  Scope              Indroduction - General - Scope
1.2    Expectations       Introduction - Expectations
2      Background         Background
2.1    Early Development  Background - Early Development
...

键的子级别没有固定数量,但它始终为数字格式。有什么想法吗?

【问题讨论】:

  • 您可能需要将其从“平面”数据结构转换为基于树的数据结构;一旦它们处于基于树的分层视图中,这将非常容易。

标签: c# list dictionary key-value string-concatenation


【解决方案1】:

在字符串中放置一个分隔符,您可以将其分开,通常是分号 (;)。但你可以使用更多。

如果您使用分号,请确保将它们从字符串中去掉。

【讨论】:

    【解决方案2】:

    此解决方案可能不是您能想到的最漂亮的解决方案,但如果您知道自己的要求真的那么简单,您可能不想过度设计它,而直接采用这种方法- 请注意,大部分代码只是正确呈现“-”部分的样板;实际算法部分代码不多:

    var dic = new Dictionary<string, string>();
          dic.Add("1", "Introduction");
          dic.Add("1.1", "General");
          dic.Add("1.1.1", "Scope");
          dic.Add("1.2", "Expectations");
          dic.Add("2", "Background");
          dic.Add("2.1", "Early Development");
    
          foreach (var kvp in dic)
          {
            string item = String.Empty;
    
            int length = kvp.Key.Length - 2;
            while (length > 0)
            {
              var parent = dic[kvp.Key.Substring(0, length)];
              if (!String.IsNullOrEmpty(item))
                item = String.Format("{0} - {1}", parent, item);
              else
                item = parent;
              length -= 2;
            }
            if (!String.IsNullOrEmpty(item))
              item = String.Format("{0} - {1}", item, kvp.Value);
            else
              item = kvp.Value;
            Console.WriteLine(item);
          }
    

    【讨论】:

    • 我相信您认为这些项目将按照它们列出的顺序进行处理。事实并非如此。 Dictionary 集合是无序的。您需要将它们放在List 中,或者在迭代之前对它们进行排序(可能按键的字符串长度排序,应该可以)。
    • 嗨 - 感谢您的指出,我应该提到这一点。我的猜测是排序将是问题的最小部分:-) 而且代码需要重构以更具表现力;我的主要观点是,如果需求真的这么简单,只需几行代码就可以解决。如果要求更复杂,我认为值得尝试一些更复杂的东西,比如您在对 OP 问题的评论中建议的方向:)
    • 另请注意,只要值是个位数,它就可以很好地工作。例如,1.10.1 将不起作用。正如你所说,简单的要求。
    【解决方案3】:

    如果您只需要输出显示,请使用 Maate 的答案。如果你在一个集合中需要这个,下面是一个开始(但它只升级了一个级别):

    Dictionary<string, string> d = new Dictionary<string, string>();
    d.Add("1", "Introduction");
    d.Add("1.1", "General");
    d.Add("1.1.1", "Scope");
    d.Add("1.2", "Expectations");
    d.Add("2", "Background");
    d.Add("2.1", "Early Development");
    
    var links = from key in d.Keys
                from subKey in d.Keys
                where subKey.StartsWith(key) && (subKey.Length == key.Length + 2)
                select new
                {
                    Key = key,
                    SubKey = subKey
                };
    
    var a = from key in d.Keys
            join link in links on key equals link.SubKey into lj
            from sublink in lj.DefaultIfEmpty()
            select new
            {
                Key = key,
                Value = d[key],
                Concatenation = (sublink == null ? string.Empty : d[sublink.Key] + " - ") + d[key]
            };
    

    它获取链接,然后使用从字典到链接的左连接来获取连接。就像我说的,它只升级了一个级别,所以这不是一个完整的解决方案。需要无限递归。

    【讨论】:

      【解决方案4】:

      这显然需要清理并提高效率,但您可以使用递归方法非常简单地做到这一点:

      static string GetConcatenationRecursively(Dictionary<string, string> d, string key)
      {
          if (key.Length == 1)
          {
              return d[key];
          }
          else
          {
              return string.Format(
                  "{0} - {1}",
                  GetConcatenationRecursively(d, key.Substring(0, key.LastIndexOf('.'))),
                  d[key]);
          }
      }
      

      这将被称为:

      Dictionary<string, string> d = new Dictionary<string, string>();
      d.Add("1", "Introduction");
      d.Add("1.1", "General");
      d.Add("1.1.1", "Scope");
      d.Add("1.2", "Expectations");
      d.Add("2", "Background");
      d.Add("2.1", "Early Development");
      
      List<Tuple<string, string, string>> list = new List<Tuple<string, string, string>>();
      foreach (string key in d.Keys)
      {
          list.Add(new Tuple<string, string, string>(key, d[key], GetConcatenationRecursively(d, key)));
      }
      

      也需要大量的错误处理;这显然假设了一个格式良好的输入。但你应该可以从这里拿走它。

      【讨论】:

      • 抱歉,我将此帖子标记为过早回答。上面的方法效果很好,但有时我确实有带有两位数数字的键。我应该在我原来的问题中提到这一点。我如何调整它以允许这样做?谢谢
      • 好点。编辑帖子以将key.Length - 2 切换为key.LastIndexOf('.');这应该可以解决问题。
      猜你喜欢
      • 1970-01-01
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2021-11-18
      • 1970-01-01
      相关资源
      最近更新 更多