1. 序章

このチュートリアルでは、英数字のStringを含まれている数値で並べ替える方法を見ていきます。 複数の文字列を残りの数字で並べ替える前に、文字列からすべての非数字文字を削除することに焦点を当てます。

空のStringや無効な数値などの一般的なエッジケースを見ていきます。

最後に、ソリューションを単体テストして、期待どおりに機能することを確認します。

2. 問題の概要

始める前に、コードで何を達成したいかを説明する必要があります。 この特定の問題について、次の仮定を行います。

  1. 文字列には、数字のみ、文字のみ、またはその2つの組み合わせを含めることができます。
  2. 文字列内の数値は整数でも倍精度でもかまいません。
  3. 文字列内の数字が文字で区切られている場合は、文字を削除して数字をまとめる必要があります。 たとえば、2d323になります。
  4. 簡単にするために、無効な番号または欠落している番号が表示された場合は、それらを0として扱う必要があります。

これが確立されたら、私たちのソリューションに固執しましょう。

3. 正規表現ソリューション

最初のステップは入力文字列内の数値パターンを検索することなので、一般に正規表現として知られる正規表現を使用できます。

最初に必要なのは正規表現です。 入力Stringからの小数点だけでなくすべての整数を保存したいと思います。 次の方法で目標を達成できます。

String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]"

String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");

何が起こっているのか簡単に説明しましょう:

  1. ‘[^]’ –否定されたセットを示します。したがって、囲まれた正規表現で指定されていない文字をターゲットにします。
  2. ‘\ d’ –任意の数字に一致(0 – 9)
  3. ‘。’–任意の「。」に一致します。 キャラクター

次に、 String.replaceAll メソッドを使用して、正規表現で指定されていない文字を削除します。 これにより、目標の最初の3つのポイントを確実に達成できます。

次に、空で無効な Strings が0を返し、有効なStringsが有効なDoubleを返すように、いくつかの条件を追加する必要があります。

if("".equals(digitsOnly)) return 0;

try {
    return Double.parseDouble(digitsOnly);
} catch (NumberFormatException nfe) {
    return 0;
}

これでロジックは完成です。 あとはコンパレータに接続するだけで、簡単に並べ替えることができますリスト入力の文字列。 

コンパレータを必要な場所から返すための効率的なメソッドを作成しましょう。

public static Comparator<String> createNaturalOrderRegexComparator() {
    return Comparator.comparingDouble(NaturalOrderComparators::parseStringToNumber);
}

4. テスト、テスト、テスト

機能を検証するためのテストなしのコードは何が良いですか? 簡単な単体テストを設定して、すべてが計画どおりに機能することを確認しましょう。

List<String> testStrings = 
  Arrays.asList("a1", "d2.2", "b3", "d2.3.3d", "c4", "d2.f4",); // 1, 2.2, 3, 0, 4, 2.4

testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());

List<String> expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.f4", "b3", "c4");

assertEquals(expected, testStrings);

この単体テストでは、計画したすべてのシナリオを詰め込みました。 無効な数値、整数、小数、および文字で区切られた数値はすべて、testStrings変数に含まれています。

5. 結論

この短い記事では、英数字の文字列をその中の数字に基づいて並べ替える方法を示しました。正規表現を使用して、大変な作業を行っています。

入力文字列を解析するときに発生する可能性のある標準の例外を処理し、単体テストでさまざまなシナリオをテストしました。

いつものように、コードはGitHubにあります。