2016-08-18 9 views
1

文字と数字を含む文字列を並べ替えるコンパイラがありますが、私が探している方法でそれらを並べ替える正規表現を識別できないようです。整数を含む文字列をコンパレータで並べ替える

私はthis questionを私のコンパレータのリファレンスとして使用しました。

array={string-a01,string-a20,string-a100,string-b01,string-b20,string-b100,string-c01,string-c20,string-c100 etc.} 

Collections.sort(array, new Comparator<String>(){  
    public int compare(String o1, String o2) { 
     return extractInt(o1) - extractInt(o2); 
    } 

    int extractInt(String s) { 
     String num = s.replaceAll("\\D", ""); 
     return num.isEmpty() ? 0 : Integer.parseInt(num); 
    } 
}); 

for (String element : array) { 
    System.out.println(element); 
} 

コンパレータを導入する前に出力されました:
string-a01, string-a100, string-a20, string-b01, string-b100, string-b20, string-c01, string-c20, string-c100

このコードが生成する出力は次のとおりです。私はそれが生成したい出力がある
string-a01, string-b01, string-c01 string-a20, string-b20, string-c20 string-a100, string-b100, string-c100


string-a01, string-a20, string-a100, string-b01, string-b20, string-b100, string-c01, string-c20, string-c100


編集:説明のために編集されています。コンパレータが追加される前に配列が変更され、出力されました。

答えて

2

。あなたは手紙エンディングの一部、および桁の部分を抽出し、複合コンパレータを使用して、それらを比較することができます

String[] array = { "string-a20", "string-a01", "string-b01", 
    "string-b20", "string-c01", "string-c20", 
    "string-a100", "string-b100", "string-c100" }; 

Pattern p = Pattern.compile("^.*?-([A-Za-z]+)(\\d+)$"); 

List<String> result = Arrays.stream(array) 
    .map(p::matcher) 
    .filter(Matcher::find) 
    .sorted(Comparator.comparing((Matcher m) -> m.group(1)) // Compare the letter part 
     .thenComparingInt(m -> Integer.parseInt(m.group(2)))) // Compare the number part 
    .map(m -> m.group(0)) // Map back to String 
    .collect(Collectors.toList()); 

System.out.println(result); 

出力:持っていることのマイナス面で

[string-a01, string-a20, string-a100, string-b01, string-b20, string-b100, string-c01, string-c20, string-c100] 

レガシーバージョン( Matcher秒を再作成するには):

Arrays.sort(array, new Comparator<String>() { 

    Pattern p = Pattern.compile("^.*?-([A-Za-z]+)(\\d+)$"); 

    @Override 
    public int compare(String o1, String o2) { 
     Matcher m1 = p.matcher(o1); 
     Matcher m2 = p.matcher(o2); 

     if(!(m1.find() && m2.find())) 
      return 0; // Or throw a format exception 

     int comparison = m1.group(1).compareTo(m2.group(1)); 
     return comparison != 0 
      ? comparison 
      : Integer.compare(Integer.parseInt(m1.group(2)), Integer.parseInt(m2.group(2))); 
    } 

}); 
+1

私が探していたすべてのことをinitalの質問が尋ねなかったので私は別の更新をしました。問題は、次のような注文です:b01、b100、b11、c01、c100、c11 ...配列は動的に生成され、元の配列で問題が起こらないことが分かった – Jon

+1

@Jon、うん、私はそれを見ていたが、もう少し複雑だ。 –

+1

@ジョン、私は答えを変更しました。これは機能しますか? –

1

extractIntメソッドのアルファベット文字を削除しているため、比較に使用できません。

あなたは、デフォルトを使用して、それらを並べ替えるなる、なしComparatorで辞書式ソートアルゴリズム(java.lang.String実装をComparable<String>)、それらを並べ替える必要があります。

// test array 
String[] s = {"string-a01","string-a01","string-b01","string-b02","string-c02","string-c02"}; 

// sorting with null Comparator, will sort if the type implements Comparable - 
// which String does 
Arrays.sort(s); 

// printing in human-readable form 
System.out.println(
    Arrays.toString(s) 
); 

出力

[string-a01, string-a01, string-b01, string-b02, string-c02, string-c02] 

ノートあなたは(WHIの重複を削除したい場合は

  • chが質問からあなたの意図かもしれない - 代わりにTreeSetに配列要素を追加し、明確ではない):あなたのソートアルゴリズムは212の前に来るように行動しなければならない場合

    Set<String> deduplicated = new TreeSet<>(Arrays.asList(s)); 
    
  • 、あなたは整数を抽出する必要があります要素からを削除せずに値を削除し、それ以外の部分が等しい場合にのみ比較してください。

    string部分は実際には"string"以外の何かであると仮定すると
+0

なぜあなたは使用しないラムダ、どのようにこのような状況を考えると、 'Arrays.sort'より任意の "簡単に" Javaの8ストリームAPIを使用している – GingerHead

+0

@GingerHeadを簡単に? – Mena

+0

例えば、 'Arrays.sort(s、(a、b) - > a.length() - b.length());' – GingerHead

1

あなたはt彼は "先導弦"、すなわち桁までの全てを指します。先頭の文字列が等しい場合は、後続の数字を比較します。

文字列を「文字列」と「整数」の部分に分割するには、最初に「最初の末尾の桁」、つまり文字列内の最初の文字の位置文字列の末尾:

int firstTrailingDigit(String s) { 
    int i = s.length(); 
    while (i > 0 && Character.isDigit(s.charAt(i - 1))) { 
    --i; 
    } 
    return i; 
} 

次に、あなたのコンパレータでこれを使用することができます。

public int compare(String a, String b) { 
    int ftdA = firstTrailingDigit(a); 
    int ftdB = firstTrailingDigit(b); 

    // Get the leading strings, and compare. 
    String sA = a.substring(0, ftdA); 
    String sB = b.substring(0, ftdB); 
    int compareStrings = sA.compareTo(sB); 
    if (compareStrings != 0) { 
    // If they're not equal, return the result of the comparison. 
    return compareStrings; 
    } 

    // Get the trailing numbers from the strings, and compare. 
    int iA = Integer.parseInt(a.substring(ftdA)); 
    int iB = Integer.parseInt(b.substring(ftdB)); 
    return Integer.compare(iA, iB); 
} 

Ideone demo

入力:

String[] array = {"string-a01","string-a20","string-a100","string-b01","string-b20","string-b100","string-c01","string-c20","string-c100"}; 

出力:

[string-a01, string-a20, string-a100, string-b01, string-b20, string-b100, string-c01, string-c20, string-c100] 
関連する問題