【问题标题】:String splitting and wrapping字符串拆分和包装
【发布时间】:2014-07-01 05:07:37
【问题描述】:

假设给我这个字符串-

String A_Old[]="010.011.100.000.111";

在每次出现 "000" 时,我都希望 断开字符串并将末端包裹在字符串的前面。结果应该是这样的-

String A_New[]="111.010.011.100";

任何有关如何解决此问题的帮助将不胜感激。 另外,“000”多次出现时该怎么办?

String A_Old[]="010.011.100.000.111.001.011.000.101.110";

应该转换为:

String A_New[]="101.110.111.001.011.010.011.100";

java 或 c++ 中的代码被理解和欣赏。


编辑

这是我认为可行的-

String b[]=A_Old.split(".000.",2);    //should split the string in 2 parts.
A_New=b[1].concat(b[0]);              // concatenation with a loss of a period

我被告知要避免丢失期间以及不使用虚拟变量。两者都在这里失败。关于如何解决这个问题的任何想法?

【问题讨论】:

  • 我不知道如何解决这个问题。我被告知不要使用虚拟变量。此外,句号给我带来了很多麻烦。
  • 对于 Java(低于 8),您将需要使用 Stringsplit 方法、ArraysasList 方法、reverse 的某种组合Collections 的方法,CollectiontoArray 方法和 Apache commons StringUtilsjoin 方法,按此顺序。我建议分别研究每一个的 Javadocs。
  • 已接受的答案不提供递归解决方案,甚至没有提供中间变量的解决方案。现在这个要求放宽了吗?有一个更新的 Perl 解决方案提供了两者,将翻译到其他强大的语言(如 Java)留给读者一个练习。 ;)
  • 感谢@DavidO,但正如您所说的那样,我已经放松了递归解决方案部分。你不会想剥夺我自学的机会吧? :) 祝你有美好的一天

标签: java c++ string-split


【解决方案1】:

要旋转列表,您需要拆分然后按您想要的顺序连接。您可能想检查空格/是否是最后一个元素。

public static void main(String[] args)
{
    String inString = "010.011.100.000.111";
    String outString = "";
    String[] arr = inString.split("\\.000\\.");
    outString = arr[0];
    for(int i = 1; i < arr.length; i++)
    {
      outString = outString + arr[i];
    }

    System.out.println(outString);
}

【讨论】:

  • 你能告诉我你为什么使用" split("\\.000\\.") "
  • Java 将 Split 字符串解释为 RegEx,它考虑 .字符匹配任何单个字符。仅匹配文字 .你必须逃避它,因此\。但是在 Java 字符串中 \ 是一个转义字符,所以你必须转义它,因此 \\.
【解决方案2】:

通过在java中使用Split方法和反向forloop

public static void main(String[] args) {
 //insert code here

     String A_Old="010.011.100.000.111.001.011.000.101.110";
     String A_new ="";
     String newe[]=A_Old.split("\\.000");

     for(int i=newe.length-1;i>=0;i--){
         A_new+=newe[i];

     }
     System.out.print(A_new.replaceFirst("\\.", ""));
 }

【讨论】:

  • 仍然需要让 '.000.' 序列中的 'dot' 字符可选,以防它出现在字符串的开头或结尾。
  • 是的,事实上,(我可能是错的,但是......)Java 的 split 采用正则表达式,因此点将被视为匹配任何内容的元字符,而不是文字点.
  • 是的,这正是我试图模仿的。但是,有没有我可以使用的递归函数?
  • @DavidO 好吧,我不打算要求递归解决方案。我期待自己解决这部分问题。你能减少敌意吗?我已经知道我以前哪里出错了,显然我之前错过了一些关于正则表达式 int 的东西
【解决方案3】:

我在java中试过了:

public static String convert(String in) {
    String[] strs = in.split("\\.*000\\.*");
    StringBuilder sb = new StringBuilder();
    for (int i = strs.length - 1; i >= 0; --i) {
        sb.append(strs[i]);
        if (i > 0 && strs[i - 1].length() > 0) {
            sb.append(".");
        }
    }
    return sb.toString();
}

public static void main(String[] args) {
    System.out.println(convert("010.011.100.000.111"));
    System.out.println(convert("010.011.100.000.111.001.011.000.101.110"));
    System.out.println(convert("010.011.100.111"));
    System.out.println(convert("000.010.011.100.111"));
    System.out.println(convert("010.011.100.111.000"));
    System.out.println(convert("000.010.011.100.111.000"));
}

输出:

111.010.011.100
101.110.111.001.011.010.011.100
010.011.100.111
010.011.100.111
010.011.100.111
010.011.100.111

【讨论】:

  • 这很有帮助。你能解释一下你为什么这样做吗? split("\\.*000\\.*");
  • 这是一个正则表达式,\\.* 表示. 可以出现0 次或1 次,因此它可以通过000000..000.000. 分割字符串。
【解决方案4】:

“没有虚拟变量”听起来像是在寻求递归解决方案。这是一个 Scheme 类吗?

这是一个 Perl 解决方案。 C++11 足够高级,可以提供这里演示的大部分功能:

my @tests = (
    '010.011.100.000.111',
    '010.011.100.000.111.001.011.000.101.110'
);

foreach ( @tests ) {
  print "$_ => ", rotate($_), "\n";  # Call our rotate routine, and show results.
}

sub rotate {
  # Split the string into components, reverse their order, join them with '.'
  return join('.', reverse split /(?:^|\.)000(?:\.|$)/, shift);
}

没有虚拟变量。事实上,也没有显式变量。

拆分正则表达式的工作原理如下:

(?:^|\.) # Match either start of string, or a dot.
000      # Match three zeros.
(?:\.|$) # Match either a dot, or the end of string.

这允许000 出现在字符串中的任何位置(包括开头或结尾)。如果它出现在开头,则不需要前导点。如果它出现在末尾,则不需要尾随点。在其他任何地方,点必须围绕000

更新: 这是使用 Perl 的递归解决方案。根据我对 Java 解决方案的阅读(我不是 Java 人),对于具有一定 Java 背景的人来说,翻译似乎应该很简单。

my @tests = (
    '010.011.100.000.111',
    '010.011.100.000.111.001.011.000.101.110'
);

foreach ( @tests ) {
  print "($_)  =>  (", rotate($_), ")\n";
}

sub rotate {
  my( $ok, $rest ) = split /(?:^|\.)000(?:\.|$)/, $_[0], 2;
  return $ok unless defined $rest;
  return join( '.', rotate($rest), $ok);
}

更新 2: 这是另一个 Perl 解决方案,它消除了任何显式变量,只使用子程序参数:

my @tests = (
    '010.011.100.000.111',
    '010.011.100.000.111.001.011.000.101.110'
);

foreach ( @tests ) {
  print "($_)  =>  (", rotate($_), ")\n";
}

sub rotate {
  return sub {
    return $_[0] unless defined $_[1];
    return join( '.', rotate($_[1]), $_[0]);
  }->( split /(?:^|\.)000(?:\.|$)/, shift, 2 );
}

我不知道如何翻译那个 Java。我怀疑翻译会变得更加困难,尽管我相信一定存在语义上等效的 C++11 解决方案。

【讨论】:

  • 谢谢,我发现这有助于理解拆分正则表达式的工作原理。但是,我不熟悉 PERL,所以我不确定它在 java 中的工作方式是否相同。
  • 至少我知道它在某种程度上被证明是有帮助的,尽管除了 Java 或 C++ 要求之外,它确实提供了一个不使用中间变量的递归解决方案,即使 '000' 出现在字符串的开头或结尾。如果我能再找到 30 分钟,我可能会将最终解决方案翻译成 C++11,只是为了好玩。不过不要屏住呼吸。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
相关资源
最近更新 更多