web-dev-qa-db-ja.com

Java-文字列を数字と文字で分割

たとえば、このような文字列C3H20IO

私がやりたいのは、この文字列を分割して、次のようにすることです。

Array1 = {C,H,I,O}
Array2 = {3,20,1,1}

1の3番目の要素としてArray2は、I要素の単原子の性質を示します。 Oについても同様です。それは実際に私が苦労している部分です。

これは化学方程式なので、名前や原子の数などに応じて要素を分離する必要があります。

12
Azazel

あなたはこのアプローチを試すことができます:

String formula = "C3H20IO";

//insert "1" in atom-atom boundry 
formula = formula.replaceAll("(?<=[A-Z])(?=[A-Z])|(?<=[a-z])(?=[A-Z])|(?<=\\D)$", "1");

//split at letter-digit or digit-letter boundry
String regex = "(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)";
String[] atoms = formula.split(regex);

出力:

原子:[C、3、H、20、I、1、O、1]

これで、すべての偶数のインデックス(0、2、4 ...)はアトムになり、奇数のインデックスは関連する番号になります。

String[] a = new String[ atoms.length/2 ];
int[] n = new int[ atoms.length/2 ];

for(int i = 0 ; i < a.length ; i++) {
    a[i] = atoms[i*2];
    n[i] = Integer.parseInt(atoms[i*2+1]);
}

出力:

a:[C、H、I、O]
n:[3、20、1、1]

8
Maljam

正規表現を使用して、Matcher.find()メソッドを使用して入力をスライドすることができます。

ここにそれがどのように見えるかの大まかな例を示します:

    String input = "C3H20IO";

    List<String> array1 = new ArrayList<String>();
    List<Integer> array2 = new ArrayList<Integer>();

    Pattern pattern = Pattern.compile("([A-Z][a-z]*)([0-9]*)");
    Matcher matcher = pattern.matcher(input);               
    while(matcher.find()){
        array1.add(matcher.group(1));

        String atomAmount = matcher.group(2);
        int atomAmountInt = 1;
        if((atomAmount != null) && (!atomAmount.isEmpty())){
            atomAmountInt = Integer.valueOf(atomAmount);
        }
        array2.add(atomAmountInt);
    }

ListからArrayへの変換が欠落していることはわかっていますが、問題への取り組み方がわかるはずです。

4
Alexander

REGEXおよびArrayListを使用して保存されたデータを使用しないアプローチ:

String s = "C3H20IO";

char Chem = '-';
String val = "";
boolean isFisrt = true;
List<Character> chemList = new ArrayList<Character>();
List<Integer> weightList = new ArrayList<Integer>();
for (char c : s.toCharArray()) {
    if (Character.isLetter(c)) {
        if (!isFisrt) {
            chemList.add(Chem);
            weightList.add(Integer.valueOf(val.equals("") ? "1" : val));
            val = "";
        }
        Chem = c;
    } else if (Character.isDigit(c)) {
        val += c;
    } 
    isFisrt = false;
}
chemList.add(Chem);
weightList.add(Integer.valueOf(val.equals("") ? "1" : val));

System.out.println(chemList);
System.out.println(weightList);

出力:

[C, H, I, O]
[3, 20, 1, 1]
4
mmuzahid

これは、各要素が大文字で始まると想定して機能します。つまり、「Fe」がある場合、「FE」として文字列で表すことはできません。基本的に、大文字で文字列を分割し、新しい文字列を文字と数字で分割し、新しい分割に数字が含まれていない場合は「1」を追加します。

        String s = "C3H20IO";
        List<String> letters = new ArrayList<>();
        List<String> numbers = new ArrayList<>();

        String[] arr = s.split("(?=\\p{Upper})");  // [C3, H20, I, O]
        for (String str : arr) {  //[C, 3]:[H, 20]:[I]:[O]
            String[] temp = str.split("(?=\\d)", 2);
            letters.add(temp[0]);
            if (temp.length == 1) {
                numbers.add("1");
            } else {
                numbers.add(temp[1]);
            }
        }
        System.out.println(Arrays.asList(letters)); //[[C, H, I, O]]
        System.out.println(Arrays.asList(numbers)); //[[3, 20, 1, 1]]
2
anaxin

C12O2Siのようなアイテムを抽出するために)ゼロ幅の先読み正規表現を使用して大文字で分割し、各アイテムを要素とその数値の重みに分割することをお勧めします:

List<String> elements = new ArrayList<>();
List<Integer> weights = new ArrayList<>();

String[] items = "C6H12Si6OH".split("(?=[A-Z])");  // [C6, H12, Si6, O, H]
for (String item : items) {
    String[] pair = item.split("(?=[0-9])", 2);    // e.g. H12 => [H, 12], O => [O]
    elements.add(pair[0]);
    weights.add(pair.length > 1 ? Integer.parseInt(pair[1]) : 1);
}
System.out.println(elements);  // [C, H, Si, O, H]
System.out.println(weights);   // [6, 12, 6, 1, 1]
1
Alex Salauyou

入力長のサイズで(ループ用に)作成し、次の条件を追加します

if(i==number)
// add it to the number array

if(i==character)
//add it into character array
1
Thesoham24

これはいいですか? (splitを使用しない)

正規表現のデモ

String line = "C3H20ZnO2ABCD";
String pattern = "([A-Z][a-z]*)(((?=[A-Z][a-z]*|$))|\\d+)";

Pattern r = Pattern.compile(pattern);

Matcher m = r.matcher(line);

while (m.find( )) {
     System.out.print(m.group(1));
     if (m.group(2).length() == 0) {
         System.out.println(" 1");
     } else {
         System.out.println(" " + m.group(2));
     }
  }

IDEONE DEMO

1
rock321987

次の2つのパターンを使用できます。

  • [0-9]
  • [a-zA-Z]

それぞれで2回分割します。

List<String> letters = Arrays.asList(test.split("[0-9]"));
List<String> numbers = Arrays.asList(test.split("[a-zA-Z]"))
            .stream()
            .filter(s -> !s.equals(""))
            .collect(Collectors.toList());

if(letters.size() != numbers.size()){
        numbers.add("1");
    }
0
abyversin

私はこれを次のように行いました

ArrayList<Integer> integerCharacters = new ArrayList();
ArrayList<String> stringCharacters = new ArrayList<>();

String value = "C3H20IO"; //Your value 
String[] strSplitted = value.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"); //Split numeric and strings

for(int i=0; i<strSplitted.length; i++){

    if (Character.isLetter(strSplitted[i].charAt(0))){
        stringCharacters.add(strSplitted[i]); //If string then add to strings array
    }
    else{
        integerCharacters.add(Integer.parseInt(strSplitted[i])); //else add to integer array
    }
}
0
Shree Krishna

(?<=\D)(?=\d)のような正規表現を使用して文字列を分割できます。これを試して :

String alphanum= "abcd1234";
String[] part = alphanum.split("(?<=\\D)(?=\\d)");
System.out.println(part[0]);
System.out.println(part[1]);

出力されます

abcd 1234

0
Karthika