在Java中对齐文本

我必须读取一个整数,它将是后续行的长度。 (文本行永远不会超过提供的长度)。

然后我必须阅读每行文本并尽可能均匀地将空格转换为下划线。 例如:

我将输入行长度30.然后一行文本Hello this is a test string 。 然后将所有空格转换为下划线并填充,以便文本填充给定的行长度,如下所示: Hello__this__is__a_test_string 。 正如您所看到的,原始文本的长度为27个字符,因此要将其填充为30个字符,我必须在原始文本中添加3个额外的空格,然后将这些空格转换为下划线字符。

请问你能告诉我一个可以解决这个问题的方法吗?

我所做的是将句子分成单词。 然后计算出需要添加多少空格。 然后迭代单词并为每个单词添加一个空格,直到用完要添加的空格。 如果你有足够的空格,你需要在单词中添加多个单词(就像你有5个单词,但需要添加13个空格),只需将剩余的空格数除以单词数,然后将该数字加到每个单词中。先说话。 然后你可以取余数并迭代添加空格的单词,直到你完成为止。 还要确保只向句子中的最后一个单词添加空格。

我最近不得不在Java中做类似的事情。 代码本身相对简单。 我发现的花费时间最长,是围绕着理由过程。

我开始逐步制定如何手动certificate文本的方法。

  1. 找出这条线有多长
  2. 找出字符串在所述行上的长度
  3. 计算添加到字符串所需的空格数以等于行长度
  4. 找出字符串中单词之间有多少间隙
  5. 计算要添加到字符串中每个间隙的空格数
  6. 将结果添加到每个间隙
  7. 计算连续添加到每个间隙的额外空格数(如果间隙数不能被要添加的空格数除尽。例如,如果有5个间隙但需要添加6个空格)
  8. 为间隙添加额外的空间
  9. 将空格转换为下划线
  10. 返回字符串

这样做使编码算法对我来说简单得多!

找出所述线上的线和线的长度

你说你已经读过行长和行上的文字,所以你已经完成了1和2。 2是一个简单的string.length()调用。

计算添加到字符串所需的空格数等于行长度只是取行长度并减去字符串的长度。

 lineLength - string.length() = noofspacestoadd; 

找出字符串中所有单词之间有多少间隙

这可能有不止一种方法。 我发现最简单的方法是将字符串转换为char [],然后遍历检查”的字符,并设置计数何时找到”

计算要添加到每个间隙的空间数

这是一个简单的除法计算!

 noofgaps / noofspacestoadd = noofspacestoaddtoeachgap; 

注意:您必须确保使用整数进行此除法! 因为5/2 = 2.5,所以你知道你必须在单词之间的每个间隙添加2个空格,并且使用int的分区截断十进制数以形成整数。

将结果添加到每个间隙

在能够添加添加到每个间隙所需的字符串数之前,您需要将此数字转换为一个空格字符串。 因此,您需要编写一个方法,将给定的整数转换为等于给定数字的空格字符串。 同样,这可以通过不同方式完成。 我这样做的方式是这样的

 String s = ""; for(int i=noofspacestoaddtoeachgap; i>0; i--) { s+= " "; } return s; 

我这样做的方法是将字符串转换为子字符串数组,子字符串是数组中的每个字。 如果你在javadoc中查找String类,你应该找到你可以用来实现这个的String类中的方法!

如果有了子串数组,则可以在每个子字符串的末尾添加空格字符串以形成新的子字符串!

计算多少额外空间

这又是一个简单的计算。 使用%运算符,您可以执行类似于我们之前所做的除法的余数除法。

 noofgaps % noofspacestoadd = noofspacestoaddtoeachgap; 

计算结果为我们提供了certificate文本合理性所需的额外空格数。

在每个间隙中连续添加额外的空格

这可能是算法中最困难的部分,因为你必须找出一种迭代单词之间每个间隙的方法,并添加一个额外的空间,直到没有剩余的额外空间来添加!

返回字符串

 return String; 

让我们试着打破这个问题:

从30减去字符串的长度 – 这是你将在某处添加的额外空格的数量(在这种情况下为3)。

计算现有空间的数量(在这种情况下为5)。

现在您知道需要尽可能均匀地将第一批额外空格分配到现有空间中(在这种情况下,将3分配到5)。

想想你将如何在现实生活中分发这样的东西,比如把球分到水桶里。 你可能会在你的水桶中旋转,在每个水桶中丢球,直到你用完为止。 那么请考虑如何在java代码中实现这一点(提示:查看不同类型的循环)。

我将采用的方法是使用带有正则表达式替换的循环。

  1. 用下划线替换所有空格。
  2. 对于使长度达到所需长度所需的每个字符,请用两个下划线替换单个下划线。 使用正则表达式确保仅在所需数量的下划线尚不存在的情况下才会发生这些替换。 请参阅JavaDoc for .ReplaceFirst() 。 您还需要考虑必须用三元组替换双下划线的可能性。

在进行初始替换之后,我建议你使用while循环,以字符串的长度为界,小于目标大小。 初始化int numUnderscores = 1; 在外面。 然后循环内的步骤将是:

  1. 建立替换模式。 这应该是"/[^_](_{" + numUnderscores + "})[^_]/" ,它表示“任何不是下划线的字符,后跟下划线字符的numUnderscores实例,后跟任何字符串不是下划线的字符“
  2. 调用.ReplaceFirst()来执行替换
  3. 检查字符串是否包含当前下划线数的任何剩余实例; 如果没有,那么你必须增加numUnderscores

显然,由于这是一个家庭作业问题,我将离开实际编写代码的过程作为练习。 如果您对其中某些部分或我所描述的逻辑结构的某些组件有特定问题,请在评论中提问!

以这种方式执行操作的好处是它可以适用于任何大小的字符串,并且可以针对不同情况进行配置。

我写了一个简单的方法来certificate文本的合理性。 它不是100%准确,但在很大程度上起作用(因为它完全忽略了标点符号,并且可能还有一些边缘情况丢失)。 此外,Word以更丰富的方式certificate文本(通过不添加空格来填补空白,但均匀分布空格的宽度,这在这里很难处理)。

 public static void justifyText (String text) { int STR_LENGTH = 80; int end=STR_LENGTH, extraSpacesPerWord=0, spillOverSpace=0; String[] words; System.out.println("Original Text: \n" + text); System.out.println("Justified Text: "); while(end < text.length()) { if(text.charAt(STR_LENGTH) == ' ') { // Technically, this block is redundant System.out.println (text.substring(0, STR_LENGTH)); text = text.substring(STR_LENGTH); continue; } end = text.lastIndexOf(" ", STR_LENGTH); words = text.substring(0, end).split(" "); extraSpacesPerWord = (STR_LENGTH - end) / words.length; spillOverSpace = STR_LENGTH - end + (extraSpacesPerWord * words.length); for(String word: words) { System.out.print(word + " "); System.out.print((extraSpacesPerWord-- > 0) ? " ": ""); System.out.print((spillOverSpace-- > 0) ? " ": ""); } System.out.print("\n"); text = text.substring(end+1); } System.out.println(text); } 

本演示文稿的第一部分包含用于文本对齐的动态编程算法。

关于这个问题最难的是定义“尽可能均匀”。

你的例子:

  Hello__this__is__a_test_string 

…使所有较长的间隙位于左侧。 岂不:

  Hello__this_is__a_test__string 

…更好地适应对问题的不精确描述,较长的间隙在输出串中均匀分布?

但是,让我们解决它,以便给出样本答案。

  • 首先,您需要知道需要插入多少额外字符 – numNewChars == lengthWanted减去inputString.length()
  • 接下来你需要计算在这些新角色之间分配这些新角色的差距 – 调用numGaps – 它是单词减去1的数量。
  • 在每个空间中,您将插入nn+1新空格。 nnumNewChars / numGaps – 整数除法; 四舍五入。
  • 现在,你需要多少次插入n+1新空格而不是n ? 剩下的就是: plusOnes = numNewChars % numGaps

这就是你需要的所有数字。 现在使用你所教过的任何方法(因为这显然是一个家庭作业问题,你不想使用课程中没有涉及的语言function或库),请查看字符串:

  • 对于第一个plusOnes空格,除了已经存在的空间外,还要插入n+1空格。
  • 对于其余空格,请插入n空格。

一个非常基本的方法如下:

 String output= ""; for(int i=0; i 

您只需要调用fullJustify()方法,其中单词列表需要与输出中所需的每行的最大宽度一起传递。

 public List fullJustify(String[] words, int maxWidth) { int n = words.length; List justifiedText = new ArrayList<>(); int currLineIndex = 0; int nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words); while (currLineIndex < n) { StringBuilder line = new StringBuilder(); for (int i = currLineIndex; i < nextLineIndex; i++) { line.append(words[i] + " "); } currLineIndex = nextLineIndex; nextLineIndex = getNextLineIndex(currLineIndex, maxWidth, words); justifiedText.add(line.toString()); } for (int i = 0; i < justifiedText.size() - 1; i++) { String fullJustifiedLine = getFullJustifiedString(justifiedText.get(i).trim(), maxWidth); justifiedText.remove(i); justifiedText.add(i, fullJustifiedLine); } String leftJustifiedLine = getLeftJustifiedLine(justifiedText.get(justifiedText.size() - 1).trim(), maxWidth); justifiedText.remove(justifiedText.size() - 1); justifiedText.add(leftJustifiedLine); return justifiedText; } public static int getNextLineIndex(int currLineIndex, int maxWidth, String[] words) { int n = words.length; int width = 0; while (currLineIndex < n && width < maxWidth) { width += words[currLineIndex++].length() + 1; } if (width > maxWidth + 1) currLineIndex--; return currLineIndex; } public String getFullJustifiedString(String line, int maxWidth) { StringBuilder justifiedLine = new StringBuilder(); String[] words = line.split(" "); int occupiedCharLength = 0; for (String word : words) { occupiedCharLength += word.length(); } int remainingSpace = maxWidth - occupiedCharLength; int spaceForEachWordSeparation = words.length > 1 ? remainingSpace / (words.length - 1) : remainingSpace; int extraSpace = remainingSpace - spaceForEachWordSeparation * (words.length - 1); for (int j = 0; j < words.length - 1; j++) { justifiedLine.append(words[j]); for (int i = 0; i < spaceForEachWordSeparation; i++) justifiedLine.append(" "); if (extraSpace > 0) { justifiedLine.append(" "); extraSpace--; } } justifiedLine.append(words[words.length - 1]); for (int i = 0; i < extraSpace; i++) justifiedLine.append(" "); return justifiedLine.toString(); } public String getLeftJustifiedLine(String line, int maxWidth) { int lineWidth = line.length(); StringBuilder justifiedLine = new StringBuilder(line); for (int i = 0; i < maxWidth - lineWidth; i++) justifiedLine.append(" "); return justifiedLine.toString(); } 

下面是maxWidth为80个字符的示例转换:以下段落包含115个单词 ,将转换后的文本写入外部文件需要55 ms

我已经测试了这段代码大约70k +单词的段落,将转换后的文本写入文件花了大约400毫秒

输入

这些特征往往使法律写作正式。 这种forms可以采取长句,复杂结构,古老和超正式词汇的forms,并注重内容以排除读者需求。 鉴于某些法律文件的重要性以及使用某些法律文件的情况的严重性,法律书面forms的某些forms是必要和可取的。 然而,并非所有法律书面forms都是合理的。 在forms上产生不透明和不精确的程度,这是不可取的。 在forms上妨碍读者理解的程度上,它是不太可取的。 特别是,当必须向非律师传达合法内容时,正式应该让位于明确的沟通。

产量

 These features tend to make legal writing formal. This formality can take the form of long sentences, complex constructions, archaic and hyper-formal vocabulary, and a focus on content to the exclusion of reader needs. Some of this formality in legal writing is necessary and desirable, given the importance of some legal documents and the seriousness of the circumstances in which some legal documents are used. Yet not all formality in legal writing is justified. To the extent that formality produces opacity and imprecision, it is undesirable. To the extent that formality hinders reader comprehension, it is less desirable. In particular, when legal content must be conveyed to nonlawyers, formality should give way to clear communication.