C#

【C#】0(ゼロ)埋めはPadLeftが爆速だった話

アイキャッチ(c_sharp)

こんにちは!
なかむぅです。

「123」というデータが来たときに

「00123」みたいにしたいなぁ

と思ったので調べてみると「0埋め」というワードが出てきたので早速試してみました。


我が社で一緒に働きませんか?

私が働く会社では、一緒に働いてくれるエンジニアを募集しています♪

我が社のココがアツイ!!
  • 未経験、第二新卒歓迎
  • 学歴・転職回数・離職期間不問
  • 残業は月15時間以下で残業代は全額支給
  • 経験者は月給23万円以上
  • 年収100万以上UP↑↑↑も可能
  • 長く働いていても年収が全然上がらないから、一気に年収を上げたい
  • 残業をしたくてしているわけではないので、残業代はしっかりと出して欲しい
  • やりたいことに挑戦させてもらえないから、自分がしてみたいことに挑戦したい
  • 通勤時間が長すぎるから、できるだけ短くしたい
  • もっと勉強したいから、書籍代など負担してくれるところに入りたい
  • 現場に駆り出されてからは放置プレイで、相談できる人も先輩も居ないので、自分の状況をちゃんと理解してくれるところで働きたい

上記内容に1つでも当てはまる場合は、ぜひご検討ください。

詳細ページ


C#で0(ゼロ)埋めする方法は3つ

C#で0(ゼロ)埋めする方法は3つあります。

  • PadLeft(string型)
  • ToString(int型)
  • string.Format(int型)

の3つです。

PadLeft(string型)

PadLeftは指定された文字を、指定された文字数になるまで左側に埋め込みます。

右寄せしたいときに使うやつですね。

0埋めしたい数字はstring型が前提です。

埋めたい文字はchar型で指定します。


文字列.PadLeft(文字数, '埋めたい文字');

たとえば

  • Hello! World
  • Hello! C#
  • Hello! .Net

といった3つの文字列を、「Hello! World」に合わせて「#」で右寄せしたい時は以下のように書きます。


static void Main(string[] args)
{
	Console.WriteLine($"{ExecPadLeft("Hello! World")}");
	Console.WriteLine($"{ExecPadLeft("Hello! C#")}");
	Console.WriteLine($"{ExecPadLeft("Hello! .Net")}");
}

private static string ExecPadLeft(string value)
{
	return value.PadLeft(12, '#');
}
結果

Hello! World
###Hello! C#
#Hello! .Net

埋めたい文字を指定せず、桁数だけ渡すと自動的に空白埋めになります。


private static string ExecPadLeft(string value)
{
	return value.PadLeft(12);
}
結果

Hello! World
   Hello! C#
 Hello! .Net

ちなみにPadRightもあります。

なので、「123」のような数字を0埋めしたい時は以下のように書きましょう。


static void Main(string[] args)
{
	Console.WriteLine($"{ExecPadLeft("1")}");
	Console.WriteLine($"{ExecPadLeft("123")}");
	Console.WriteLine($"{ExecPadLeft("12345")}");
}

private static string ExecPadLeft(string value)
{
	return value.PadLeft(5, '0');
}
結果

00001
00123
12345

12345に合わせて「0」が埋められました。

桁数を「7」に変更して、埋めたい文字を「X」にすると以下のように変化します。

好きな桁数と埋めたい文字を変更してみてください。


private static string ExecPadLeft(string value)
{
	return value.PadLeft(7, 'X'); // 7桁にしてX埋めに変更
}
結果

XXXXXX1
XXXX123
XX12345

埋めたい文字を指定できるので、自由度の高い方法です。

ToString(int型)

int型に対して0埋めしたいときに使えます。

ToStringの引数に10進数書式指定子を使いましょう。


数値.ToString("10進数書式指定子");

5桁の数字として0埋めしたいときは、以下のように書きます。


static void Main(string[] args)
{
	Console.WriteLine($"{ExecToString(1)}");
	Console.WriteLine($"{ExecToString(123)}");
	Console.WriteLine($"{ExecToString(12345)}");
}

private static string ExecToString(int value)
{
	return value.ToString("D5");
}
結果

00001
00123
12345

「D」のあとに「0」で揃えたい桁数を入れればいいので、7桁にしたいときは「D7」にすると7桁で0埋めしてくれます。


private static string ExecToString(int value)
{
	return value.ToString("D7"); // D7に変更
}
結果

0000001
0000123
0012345

ToStringで10進数書式指定子を使わない方法

ToStringは10進数書式指定子だけでなく、0埋めして統一したい桁数分の「0」を入れることでも可能です。


数値.ToString("桁数分の0");

5桁で揃えたい場合は、引数に「0」を5つ指定します。


private static string ExecToString(int value)
{
	return value.ToString("00000");
}
結果

00001
00123
12345

ただ、この方法だと7桁で揃えたい時は「0」を7つ指定しないといけないので、揃えたい桁数が増えるたびに記述が増えてしまいます。

10進数書式指定子のほうがスッキリ書けるので、この書き方は需要なさそうですね。


private static string ExecToString(int value)
{
	return value.ToString("0000000"); // 「0」を7つに変更
}
結果

0000001
0000123
0012345

0以外は渡した文字列に変換される(余談)

結果からわかると思いますが、ToStringは「0」でしか埋めることができません。

当たり前の話ですが「1」を指定すると、そのまんま文字列の「11111」として変換されます。

数値を0以外で埋めることはないと思うので、あまり問題にはならないと思いますが(笑)


private static string ExecToString(int value)
{
	return value.ToString("11111");
}
結果

11111
11111
11111

もちろん「Hello, World!」にすると全てHello, World!になります。


private static string ExecToString(int value)
{
	return value.ToString("Hello, World!");
}
結果

Hello, World!
Hello, World!
Hello, World!

「そんなの知ってるよ」って感じですが、世の中には

「1」で埋めたいときは、「1」を引数に渡せばいいのか

と思ってしまう人も居るのです。

誰とは言いませんが。

どうしても「0」以外で埋めたい場合はPadLeftを使いましょう。

10進数書式指定子のほうが速い

ToStringは10進数書式指定子を使ったほうが書きやすいですが

どっちが速いんやろう

と思ったので測ってみると、10進数書式指定子を使ったほうが速かったです。


static void Main(string[] args)
{
	// 順番を変更すると結果が変わるので、コメントアウトして1つ1つ実行
	IntMeasurement(ExecToStringD5);
	IntMeasurement(ExecToString05);
}

private static string ExecToStringD5(int value)
{
	return value.ToString("D5");
}

private static string ExecToString05(int value)
{
	return value.ToString("00000");
}

private static int _length = 100000;
private static void IntMeasurement(Func<int, string> exe)
{
	var zeroPaddingList = new List<string>();
	var sw = new Stopwatch();
	sw.Start();
	for (int i = 0; i < _length; i++)
	{
		zeroPaddingList.Add(exe(i));
	}
	sw.Stop();

	Console.WriteLine($"{exe.Method.Name} : {sw.Elapsed}");
}
結果

ExecToStringD5 : 00:00:00.0054231
ExecToString05 : 00:00:00.0166016

書き方も速度も10進数書式指定子のほうが有利ですね。

string.Format(int型)

string.Formatで0埋めする方法もあり、ToString同様に10進数書式指定子を使います。


string.Format("{0:10進数書式指定子}", 数値);

string.Formatだと以下のような書き方になります。


static void Main(string[] args)
{
	Console.WriteLine($"{ExecStringFormat(1)}");
	Console.WriteLine($"{ExecStringFormat(123)}");
	Console.WriteLine($"{ExecStringFormat(12345)}");
}

private static string ExecStringFormat(int value)
{
	return string.Format("{0:D5}", value);
}
結果

00001
00123
12345

もちろんToString同様、0埋めして統一したい桁数分の「0」を入れることでも0埋めが可能です。


string.Format("{0:桁数分の0}", 数値);

5桁で0埋めしたい場合は以下のように書きます。


private static string ExecStringFormat(int value)
{
	return string.Format("{0:00000}", value);
}
結果

00001
00123
12345

速度も10進数書式指定子を使ったほうが速かったです。

コードは省略。

結果

ExecStringFormatD5 : 00:00:00.0116967
ExecStringFormat05 : 00:00:00.0231988

基本的にToStringと結果は同じなので、書きやすいToStringを使うのが正解だと思います。

PadLeft、ToString、string.Formatの速度

やっぱり最後は

どれが一番速いんや

となったので、測ってみました。


static void Main(string[] args)
{
	// 順番を変更すると結果が変わるので、コメントアウトして1つ1つ実行
	StringMeasurement(ExecPadLeft);
	IntMeasurement(ExecToString);
	IntMeasurement(ExecStringFormat);
}

private static string ExecPadLeft(string value)
{
	return value.PadLeft(5, '0');
}

private static string ExecToString(int value)
{
	return value.ToString("D5");
}

private static string ExecStringFormat(int value)
{
	return string.Format("{0:D5}", value);
}

private static int _length = 100000;
private static void StringMeasurement(Func<string, string> exe)
{
	// string型なのでstringのListを作成する
	var list = GetStringList();
	var zeroPaddingList = new List<string>();
	var sw = new Stopwatch();
	sw.Start();
	for (int i = 0; i < list.Count; i++)
	{
		zeroPaddingList.Add(exe(list[i]));
	}
	sw.Stop();

	Console.WriteLine($"{exe.Method.Name} : {sw.Elapsed}");
}

private static List<string> GetStringList()
{
	var list = new List<string>();
	for (int i = 0; i < _length; i++)
	{
		list.Add(i.ToString());
	}
	return list;
}

private static void IntMeasurement(Func<int, string> exe)
{
	var zeroPaddingList = new List<string>();
	var sw = new Stopwatch();
	sw.Start();
	for (int i = 0; i < _length; i++)
	{
		zeroPaddingList.Add(exe(i));
	}
	sw.Stop();

	Console.WriteLine($"{exe.Method.Name} : {sw.Elapsed}");
}
結果

ExecPadLeft      : 00:00:00.0021107
ExecToString     : 00:00:00.0054231
ExecStringFormat : 00:00:00.0116967

PadLeftが優勝。

じゃあint型もstring型に変換してから、PadLeftにしたら速くなるんじゃね!?

と思ったので、以下のコードを追加して試してみました。


private static string ExecToStringPadLeft(int value)
{
	return value.ToString().PadLeft(5, '0');
}
結果

ExecToString        : 00:00:00.0054231
ExecToStringPadLeft : 00:00:00.0053332

ToStringを挟むせいか、速度は変わらなかったです。

まとめ

記述量、速度を考えるとPadLeftが一番良さそうですね。

まぁ仕様や環境によって使い所も変わると思うので、適材適所で使いましょう。

以上、 C#の0埋めについてでした!

いやここは違うだろ

と思った方はコメントいただけると嬉しいです。

最後までお読みいただきありがとうございました!


我が社で一緒に働きませんか?

私が働く会社では、一緒に働いてくれるエンジニアを募集しています♪

我が社のココがアツイ!!
  • 未経験、第二新卒歓迎
  • 学歴・転職回数・離職期間不問
  • 残業は月15時間以下で残業代は全額支給
  • 経験者は月給23万円以上
  • 年収100万以上UP↑↑↑も可能
  • 長く働いていても年収が全然上がらないから、一気に年収を上げたい
  • 残業をしたくてしているわけではないので、残業代はしっかりと出して欲しい
  • やりたいことに挑戦させてもらえないから、自分がしてみたいことに挑戦したい
  • 通勤時間が長すぎるから、できるだけ短くしたい
  • もっと勉強したいから、書籍代など負担してくれるところに入りたい
  • 現場に駆り出されてからは放置プレイで、相談できる人も先輩も居ないので、自分の状況をちゃんと理解してくれるところで働きたい

上記内容に1つでも当てはまる場合は、ぜひご検討ください。

詳細ページ


COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です