LoginSignup
1

【Golang】文字間の複数ホワイトスペースを削除して1つのスペースに置き換える関数

Last updated at Posted at 2022-10-06

Go 言語(以下 Golang)で、文字列内の文字間にある複数スペースやタブを 1 つに変換したい。
つまり、単語間の空白を詰めたいのです。

こういうことがしたい(before-->after)
" Hello,    World  ! "         --> "Hello, World !"
"Hello,\tWorld ! "             --> "Hello, World !"
" \t\n\t Hello,\tWorld\n!\n\t" --> "Hello, World !"

「golang 文字間の複数スペースを削除する」でググっても、正規表現や strings.ReplaseAll を使った方法だったり、文字列の前後のトリムばかりだったので、自分のググラビリティとして。

TL; DR (今北産業)

  1. strings.Fields 関数を使う。
  2. strings.Fields() は、連続したホワイト・スペース(空白、タブや改行)を 1 つとして扱う strings.Split 関数の親戚。
  3. strings.Fields() で分解し、strings.Join() で再度組み合わせると単語間の空白を詰められる。
単語間を詰める関数
// TrimWordGaps は、文字列内の連続した空白文字を 1 文字のスペースに変換します。
// 具体的な使い方・サンプルは TS; DR 参照
func TrimWordGaps(s string) string {
	return strings.Join(strings.Fields(s), " ")
}

TS; DR

strings.Fields とは

func Fields
func Fields(s string) []string

Fields splits the string s around each instance of one or more consecutive white space characters, as defined by unicode.IsSpace, returning a slice of substrings of s or an empty slice if s contains only white space.
Fields | strings @ pkg.go.dev より)

【筆者訳】
Fields は、1 つ以上の連続したホワイト・スペースで囲まれている文字の周りで文字列 s を分割し、その部分文字列のスライスを返します。また、s が空白のみを含む場合は空のスライスを返します。なお、ホワイト・スペースは unicode.IsSpaceで定義されている空白文字です。

つまり、strings.Fields()strings.Slice() の変形バージョンです。

例えば strings.Slice(s, " ") は、s 内でヒットした " " ごとに分割するのに対し、strings.Fields(s) は連続している空白文字(ホワイトスペース)を 1 文字として扱い s を分割します。

動作サンプル

サンプル
package main

import (
	"fmt"
	"strings"
	"testing"
)

func TrimWordGaps(s string) string {
	return strings.Join(strings.Fields(s), " ")
}

func ExampleTrimWordGaps() {
	result := TrimWordGaps("    Hello,       World     !    ")

	fmt.Println(result)

	// Output: Hello, World !
}

func TestTrimWordGaps(t *testing.T) {
	for i, test := range []struct {
		input  string
		expect string
	}{
		{
			input:  " Hello,   World  ! ",
			expect: "Hello, World !",
		},
		{
			input:  "Hello,\tWorld ! ",
			expect: "Hello, World !",
		},
		{
			input:  " \t\n\t Hello,\tWorld\n!\n\t",
			expect: "Hello, World !",
		},
	} {
		nameTest := fmt.Sprintf("test #%d", i)

		t.Run(nameTest, func(t *testing.T) {
			actual := TrimWordGaps(test.input)
			if test.expect != actual {
				t.Fail()
			}
		})
	}
}

参考文献

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1