【问题标题】:Java string, insert a dash after every 8 characters, starting from the right [duplicate]Java字符串,每8个字符后插入一个破折号,从右边开始[重复]
【发布时间】:2012-08-12 00:58:08
【问题描述】:

在 Java 字符串中每 8 个字符后插入一个-(破折号/减号字符)的最佳方法是什么,从右侧开始?

例子:

1111 -> 1111
111111111 -> 1-11111111
1111111111111111 -> 11111111-11111111
100001111111111111111 -> 10000-11111111-11111111

我的尝试,表明我已经尝试过自己做(下面的评论问:“这是作业吗?”:

import junit.framework.TestCase;
public class InsertCharacterAfterEveryNCharacters extends TestCase {
  public static String insertSpacerAfterNCharactersFromTheRight(char spacer,
      int spacing, String string) {
    final int length = string.length();
    final int newStringCapacity = length + (int) Math.ceil(length / (double) spacing);
    StringBuilder stringBuilder = new StringBuilder(newStringCapacity);
    for (int i = length - 1; i >= 0; i--) {
      stringBuilder.append(string.charAt(i));
      if (i % spacing == 0 && i > 0) {
        stringBuilder.append(spacer);
      }
    }
    return stringBuilder.toString();
  }
  public static void testInsertSpacerAfterNCharactersFromTheRight() {
    assertEquals("", insertSpacerAfterNCharactersFromTheRight('-', 8, ""));
    assertEquals("1", insertSpacerAfterNCharactersFromTheRight('-', 8, "1"));
    assertEquals("11", insertSpacerAfterNCharactersFromTheRight('-', 8, "11"));
    assertEquals("11111111",
        insertSpacerAfterNCharactersFromTheRight('-', 8, "11111111"));
    assertEquals("1-11111111",
        insertSpacerAfterNCharactersFromTheRight('-', 8, "111111111"));
    assertEquals("11111111-11111111",
        insertSpacerAfterNCharactersFromTheRight('-', 8, "1111111111111111"));
  }
}

【问题讨论】:

  • 没什么花哨的,但是一个好的旧 for 循环可以解决问题。使用 new StringBuffer(key).insert(position, "-").toString();
  • 对于该循环,对 (string.length%8) 个字符进行第一次迭代,然后跳过 8 个字符。在循环中使用 StringBuilder,这样您就不必一直创建新的 String 对象,只需在每次迭代中附加 String 的前缀即可。
  • 你说得对,让我添加我自己的解决方案来(正确地)表明我在发布之前已经完成了一些自己的工作。
  • 关于获得 5 票推荐“insert()”的评论,这不是在每次调用时执行不必要的 ArrayCopy 吗?

标签: java string


【解决方案1】:

您不能将- 直接插入到现有的Java 字符串中,因为字符串是不可变的。但是,您可以创建一个新的 String 实例来满足您的输出格式要求。

从输入字符串的结束索引向下循环到 0。对于每次迭代:

  • 将当前索引处的值插入StringBuilder 实例的开头。
  • 使用模运算符查看是否插入了 8 个字符的倍数。如果是这样,请插入一个破折号。

如果需要,使用 StringBuilder 实例的“toString()”方法获取字符串。

【讨论】:

  • 我突然想到,如果他事先指定StringBuilder的长度会不会更好?我不确定 StringBuilder 如何在内部处理字符串。
  • 是的,可能,但我敢于衡量差异 :-) 这取决于最终字符串相对于 StringBuilder 分配的初始缓冲区的长度,以及总成本长度计算。
  • 总长度计算是简单的算术运算:string.length + string.length/8 + 1
  • @G.Bach:是的,但是内存移动操作也不是很昂贵(对于小内存块)。我们正在研究小型输入字符串的微优化。
【解决方案2】:

大概是这样的吧?

for(int i = s.length() - 1; i > 0; i -= 8)
{
    s = new StringBuffer(s).insert(i, "-").toString();
    i--;
}

【讨论】:

  • 寻找pb2q's answer。你会学到一些好东西。
  • 嗯,您能提供更多信息吗?如果您说他的代码更好,但更多信息会很好。是因为我创建了多个 StringBuffers 吗?
  • 只是好奇——如果您将 pb2q 的答案用作批评另一个答案的参考,为什么不 +1 呢?
  • @thatidiotguy 是的,我应该在我的评论中添加一些信息:首先:StringBuffer 支持同步,而 StringBuilder 不支持同步,因此根据字符串长度,这可能会稍微提高性能.第二:不需要在每次迭代时创建StringBuffer(或StringBuilder),您可以在开始时创建它并在每次for循环迭代时插入值。
  • @ametren 当我评论这篇文章时,pb2q 的答案只有 StringBuilder 解决方案,我认为这不是最合适的,但乍一看。现在我午饭后回来了,有char[] 的解决方案,这更有趣和有效(我倾向于这样编码),现在他支持我。
【解决方案3】:

从原来的String 构建一个char[]

String str = "100001111111111111111";

// add enough space for an additional "-" for every 8 chars:
char[] chars = new char[str.length() + (str.length() / 8)];

// this offset will give us the first "-" position from the LEFT:
int offset = str.length() % 8;
int idx = 0, strIdx = 0;

for (; strIdx < str.length(); idx++, strIdx++)
{
    if (((strIdx % 8) == offset) && (strIdx != 0))
        chars[idx++] = '-';
    chars[idx] = str.charAt(strIdx);
}

String str2 = new String(chars);

System.out.println(str2);

或者您可以使用StringBuilder,这可能涉及(length / 8) 数组复制操作:

StringBuilder str = new StringBuilder("100001111111111111111");
int idx = str.length() - 8;

while (idx > 0)
{
    str.insert(idx, "-");
    idx = idx - 8;
}

System.out.println(str.toString());

两种情况下的输出:

10000-11111111-11111111

请注意,这不会在索引 0 处插入连字符,如果有必要,您需要调整代码。

【讨论】:

  • 这个答案有 3 个赞成票,但我想知道:真的有必要每 8 个字符执行一次完整的System.arraycopy(value, offset, value, offset + len, count - offset);,而不是创建正确大小的缓冲区并逐步填充它吗?
  • @Robottinosino 好点,解决方案很幼稚。添加了数组操作解决方案。
  • 很棒的解决方案! :D
【解决方案4】:

所有答案似乎都包含了很多需要完成的代码。你可以使用正则表达式来做到这一点。

假设您有一个返回格式化字符串的方法。

一个简单明了的例子:

String myString = "00000000000111111111111100000000001111111000011000000";
String newString = myString.replaceAll("(.{8})(?!$)", "$1-");
return newString;

Above 等于以下更短的符号:

return myString.replaceAll("(.{8})(?!$)", "$1-");

另一个类似的短符号(在固定的硬编码字符串的情况下):

return "00000000000111111111111100000000001111111000011000000".replaceAll("(.{8})(?!$)", "$1-");

每段代码都返回以下字符串:

00000000-00011111-11111111-00000000-00111111-10000110-00000

有关正则表达式的更多信息,请参阅例如http://www.regular-expressions.info/java.html

希望这对将来的任何人都有帮助。

编辑说明: 最后一组没有 8 个字符。但是,如果它会,它不会添加另一个破折号。

【讨论】:

  • 从“右边”插入-
  • 您可以使用StringBuilder 反转字符串,将正则表达式应用于反转的字符串,然后再次反转以获得所需的结果。
  • 贵.. 但谢谢。
【解决方案5】:

上述解决方案很好,但非常复杂且冗长,我写了这个,它适用于您的输入。

public static String insertCharacterForEveryNDistanceFromRight(int distance, String original, char c){
    StringBuilder sb = new StringBuilder();
    char[] charArrayOfOriginal = original.toCharArray();
    for(int ch = charArrayOfOriginal.length ; ch > 0 ; ch--){
        if(ch % distance == 0 && ch != charArrayOfOriginal.length)
            sb.append(c).append(charArrayOfOriginal[charArrayOfOriginal.length - ch]);
        else
            sb.append(charArrayOfOriginal[charArrayOfOriginal.length - ch]);
    }
    return sb.toString();
}

然后这样称呼它......

String rightResult = InsertSpaces.insertCharacterForEveryNDistanceFromRight(8, "100001111111111111111", '-');
System.out.println(rightResult);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 2013-07-19
    • 1970-01-01
    相关资源
    最近更新 更多