【问题标题】:Is there an elegant work around to concatenation?连接是否有优雅的工作?
【发布时间】:2010-10-13 13:31:09
【问题描述】:

我正在编写一个疯狂的 libs 程序,目的是为了好玩,只是为了编写一些东西。该程序本身非常简单,但由于游戏的性质,我发现自己使用了几个连接,您将用户给定的单词放入一个句子中。是否有一种优雅的解决方法可以减少串联,甚至消除它们以获得更有效的东西?我知道最终是否使用连接都没有区别,但我很好奇是否有更优雅的方式来编写这个程序。

更新:我正在使用 java,但如果有一个通用的解决方案来转义连接,那也将不胜感激。

【问题讨论】:

  • 只是好奇你为什么要避免串联
  • 好吧,我就这么说吧,虽然这不是合适的地方,你的头像太棒了!
  • 我自己只是出于好奇而避免串联,我知道程序可以很好地处理它们。也感谢 TJB。

标签: java string concatenation


【解决方案1】:

一种解决方案可能是写出整个 mad libs 文件并放入需要替换为所选单词的特殊标记。

你刚买了一个全新的 ${NOUN1}, 它会变成${VERB1}你。

然后您可以使用例如:String.replace("${NOUN1}", noun1) 来表示所有单词。

【讨论】:

  • 请注意,我认为使用命名标记可能比使用普通 String.format 标记(如 %s、%d)更易于维护
  • 令牌不会导致相同数量的连接吗?
  • +1 用于生成比 StringBuilder/Buffer 更具可读性的代码
  • 这确实会进行字符串连接。内存字符串拼接中不要做的关键是按顺序输出字符串部分。
【解决方案2】:

您使用哪种语言?

大多数高级语言都有类似的内容:

String.Format("{0} {1} {2} {3}", word1, word2, word3, word4);

【讨论】:

  • 你可能猜到这只会隐藏串联,而不是避免它们。
  • 现在是C高级了吗?我开玩笑,但考虑到 printf 和 c 作为中级语言的重要性......
  • +1 这将给出列出的解决方案中最易读的代码。根据底层代码的实现,它还可以避免连接(这似乎是可能的)。
【解决方案3】:

有两种方法可以让你在游戏中完全避免串联:

  1. 将故事模板存储为标记集合:不可变部分和单词占位符。然后循环输出不可变部分和用户单词而不是单词占位符的集合。

  2. 编写自定义打印类,该类将使用 charAt 循环遍历模板字符串并输出单词而不是单词占位符。

【讨论】:

    【解决方案4】:

    您可以将单词放在有序数组中并使用 String.format(在 jdk 1.5 或更新版本中)或 MessageFormat.format 在 jdk 1.4 中,而不是为每个单词调用 String.replace 或不断附加到 StringBuilder。不幸的是,两者的模式格式不同。

    String myPattern = "我的 %s 吃掉了你的 %s"; // 从这里获取用户的值 字符串结果 = String.format( myPattern, (Object[])myArray );

    String myPattern = "我的 {0} 吃掉你的 {1}"; // 从这里获取用户的值 字符串结果 = MessageFormat.format(myPattern, (Object[])myArray);

    这是一个完整的程序,用命令行中的值填充字符串。

    公开课形式 { 公共静态无效主要(字符串[] args) { String pattern = "我的 %s 吃掉了你的 %s"; System.out.println(String.format(pattern, (Object[])args)); } }

    【讨论】:

      【解决方案5】:

      您的问题有两个方面。

      首先,您可能希望避免在代码中直接使用串联。然后,您可以使用运行时中的一些字符串格式化例程。这不会跳过串联,但会将它们从您的代码移动到运行时。

      其次,您可能希望更有效地进行连接。那是另一个故事。这里最重要的是为连接的字符串预分配足够大的缓冲区,因为内存重新分配非常昂贵。将子字符串复制到结果字符串中通常成本较低,而且是必要的。

      【讨论】:

      • 为 madlibs 分配足够大的缓冲区似乎是不可能的,因为用户可以提供任何大小的单词。
      • 嗯,这也可能发生,但你可以猜测长度限制是多少,比如 97 % 的概率。这将使您的实现在大多数情况下非常有效,而在所有其他情况下也相当有效。
      • 如果将字符串的不同部分按顺序写入输出流,则可以完全避免内存连接。
      【解决方案6】:

      就避免串联的一般方法而言,我没有想到任何东西。你可以做的是给自己写一些帮助类来简化你的连接工作。 然而,我想给你的一个建议是不要直接将字符串连接为

      String x = "Hi";
      String y = x + " there!";
      

      在 Java 中字符串连接的实现非常慢,因此最好使用 StringBuffer 代替,尤其是在您进行大量连接时:

      StringBuffer myStringBuffer = new StringBuffer();
      myStringBuffer.append("Hi");
      myStringBuffer.append(" there!");
      

      类似的东西。我现在没有在编译器中检查这个,但我相信你可以自己弄清楚。

      【讨论】:

      • -1 - 现代 Java 编译器会将简单的字符串连接序列编译为等效的 StringBuffer 操作序列。
      • 嗯...通常建议使用 StringBuffer 或 StringBuilder(在 C# 中)进行字符串连接。我对 Java 编译器没有足够的背景知识。您可能是对的,但是 J2ME 环境呢?相同的 Java 语法,但不同的做法。在那里你绝对不应该做字符串连接。因此,通常我会说我的“规则”仍然成立。
      【解决方案7】:

      不确定 Java,但在 PHP 和 Javascript 等其他一些语言中,创建数组并连接其所有元素会更快。

      Javascript 示例:

      var str = str1 + str2 + str3 + "str4" + str5 + "str6" + str7;
      var str = [str1, str2, str3, "str4", str5, "str6", str7].join("");
      

      PHP 示例:

      $str = $str1 . $str2 . $str3 . "str4" . $str5 . "str6" . $str7;
      $str = implode("", array($str1, $str2, $str3, "str4", $str5, "str6", $str7));
      

      如果您想在每个字符串之间放置一个分隔符,这种方法是最好的,在这种情况下,它不仅会更快,而且更紧凑和可读。

      【讨论】:

      • 看起来很奇怪,Java 没有内置这样的功能;它可能会(最终!)包含在 Java 7 中。目前,它可以是连接、StringBuilder 或第三方库。
      • 可能会在幕后进行字符串连接,或者其他类似的工作量。
      【解决方案8】:

      “避免连接”我假设您的意思是为新字符串分配空间并分配它?如果您使用的是 .NET,那么我认为 StringBuilder 应该会有所帮助。

      【讨论】:

        【解决方案9】:

        如果您有一个 String 需要经常修改它,使用 char[] 数组并在完成修改后创建一个 String 可能会解决问题。

        【讨论】:

          【解决方案10】:

          如果您愿意,当然可以在不连接的情况下执行此操作。虽然这可能不是很值得。

          这部分取决于您要在哪里显示结果。如果它在 Web 或控制台上,那么您可以将结果直接写入输出流。

          例如,如果您的模板类似于“%001 跳出 %002”,您可以:

          1) 扫描字符串以查找变量所在的位置。 2) 将字符串分解成组件列表“the”、“jumped out of the”,在这种情况下 3)遍历列表的元素和结果并将它们转储到输出,如下所示:

          PrintStream  = //get output from somewhere
          for(int i = 0; i < pieces.size()-1 ; i++){
             ps.print(peices.get(i));
             ps.print(answers.get(i));
          }
          ps.print(pieces.get(pieces.size()-1));//last one
          

          现在。我不知道您是否会称其为“优雅”。它可能会有点快。就像我说的,如果这是一个 Web 服务并且它变得超级流行等等,也许是合适的。

          如果这是一个 GUI 应用程序,您可以编写代码来分别绘制字符串,但这可能会比连接花费更多的时间。

          但是可以做的一件事是使用 ByteArrayOutputStream 并预先分配足够的空间,以便它可以包含填充的 madlib 而无需进行额外分配。那也很快。

          【讨论】:

            【解决方案11】:

            如果为了清洁,你为什么要避免串联,试着把它排好,结果可能看起来出奇的好。即使你担心性能,你也可能不需要使用字符串生成器,我相信如果你这样做一堆简单的连接(即“fdsfsd”+ var1+var2+“dsfsdf”+“tyhty”它编译成与字符串生成器相同的东西(实际上相同并且看起来更干净)。如果你连接一个字符串生成器确实有意义循环中或复杂流程中的大量内容。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-10-19
              • 2021-06-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-07-03
              • 2013-11-07
              相关资源
              最近更新 更多