我正在努力建立一个系统,将一个给定的扩展化学公式(例如C6H2NO2NO2NO2CH3
)括在括号中(如果该术语在化学中是正确的),使其成为C₆H₂(NO₂)₃CH₃
。 (在第一个实例中忽略下标或缺少下标)。问题是,我不知道重复的分子会是什么,甚至不知道它会持续多久。我如何找到并计算重复次数?
对于上下文,这是我的代码到目前为止,它从2D元素列表中生成公式:
private String getFormula(List<List<Element>> elements)
{
String formula = ""; //TODO Switch out for StringBuilder
for(List<Element> currentElement : elements)
{
formula += currentElement.get(0).getSymbol(); //Every element per list is identical, so looking at 0 will always be safe
if(currentElement.size() > 1) formula += currentElement.size(); //Only display a number if there is more than 1 element
}
return formula;
}
答案 0 :(得分:2)
This answer提供了代码:String result = source.replaceAll("(.+)\\1+", "$1")
,它取代了所有重复的子字符串。
我认为稍微修改一下代码应该做你想要的。如果使用"($1)"
作为替换,它将在括号中包装匹配。您可以逐步完成替换,并确定括号后应该出现的数字。
要阻止正则表达式捕获前面的数字,请尝试"([A-Za-z]+[1-9]*)\\1+"
。
This link解释了如何计算匹配数。它有点复杂:
Pattern pattern = Pattern.compile("([A-Za-z]+[1-9]*)\\1+");
Matcher matcher = pattern.matcher(YOUR_CHEM_STRING);
int count = 0;
String prior="";
while (matcher.find()){
if(m.group().equals(prior){
count++;
}else{
YOUR_CHEM_STRING.replaceAll("([A-Za-z]+[1-9]*)\\1+","($1)"+count);
count=0;
}
}
答案 1 :(得分:2)
编辑已更新,以便考虑订单。谢谢@JakeStanger!
第二次编辑更新以反映分子以|
结束的新情况
我使用正则表达式来分割String
,因为从给定的|
我们知道新分子在Hashmap
之后开始。我使用Hashmap
来跟踪每种类型的分子数量。最后,我遍历String result
中的每个值,并附加到 public static String factorise(String input) {
String result = "";
Map<String, Integer> molecules = new LinkedHashMap<>();
String[] res = input.split("\\|");
for (String t : res) {
//Check if we already have this element in our map
if (!molecules.containsKey(t)) {
//If not then add it and set the count to 1
molecules.put(t, 1);
} else {
//If we do then update the count by 1
molecules.put(t, molecules.get(t) + 1);
}
}
//Iterate through each molecule
for (String key : molecules.keySet()) {
if (molecules.get(key) == 1) {
//If the count is only at one, then we just need to append it.
result += key;
} else {
//Otherwise, we need the parentheces and the number of repetitions followed after
result = result + "(" + key + ")" + molecules.get(key);
}
}
return result;
}
,具体取决于它是否是一个分子。干杯!
System.out.println(factorise("C6|H2|NO2|NO2|NO2|CH3|OH|OH"));
System.out.println(factorise("HO|HO"));
运行
<script type="text/javascript" src="//cdn.datatables.net/plug-ins/1.10.11/sorting/date-uk.js"></script>
运行时产生以下内容:
运行:
C6H2(NO2)3 CH 3(OH)2
(HO)2个
建立成功(总时间:0秒)
答案 2 :(得分:1)
您计算将公式元素拆分为一个列表,然后解析它,计算连续重复次数。当计数大于1时,您将使用括号添加它。
String formula = "C6H2NO2NO2NO2CH3";
Pattern p = Pattern.compile("[a-zA-Z]+[0-9]+");
Matcher m = p.matcher(formula);
List<String> parts = new ArrayList<String>();
while(m.find()) {
parts.add(m.group());
}
String shrink = "";
int count = 0;
for(int i=0; i<parts.size(); i++) {
count++;
if(i+1 == parts.size() || !parts.get(i+1).equals(parts.get(i))) {
if(count == 1)
shrink += parts.get(i);
else
shrink += "("+parts.get(i)+")"+count;
count = 0;
}
}
System.out.println(shrink); // result = "C6H2(NO2)3CH3"
如果您能够发送元素列表,请尝试以下:
public static String shortForumla(List<List<Element>> elements) {
String shrink = "";
int count = 0;
for(int i=0; i<elements.size(); i++) {
String symbol = elements.get(i).get(0).symbol();
if(i+1 == elements.size() || !elements.get(i+1).get(0).symbol().equals(symbol)) {
if(count == 1)
shrink += symbol;
else
shrink += "("+symbol+")"+count;
count = 0;
}
}
return shrink;
}
答案 3 :(得分:1)
这是一种替代解决方案,它使用简单的字符串解析来查找匹配的重复子字符串。
public static String factorise(String input) {
StringBuilder result = new StringBuilder();
for (int start = 0; start < input.length(); start++) {
char c = input.charAt(start);
if (c >= '0' && c <= '9') {
result.append(c);
continue;
}
boolean foundRepeat = false;
for (int end = start + 1; end <= input.length(); end++) {
int length = end - start;
if (end + length > input.length()) break;
String sub = input.substring(start, end);
String nextsub = input.substring(end, end + length);
int nextpos = end + length;
int count = 1;
while (sub.equals(nextsub)) {
count++;
if (nextpos + length > input.length()) break;
nextsub = input.substring(nextpos, nextpos + length);
nextpos += length;
}
if (count > 1) {
result.append("(" + sub + ")" + count);
start += length * (count) - 1;
foundRepeat = true;
break;
}
}
if (!foundRepeat) {
result.append(c);
}
}
return result.toString();
}
示例:
C6H2NO2NO2NO2CH3
:C6H2(NO2)3CH3
CaOHOH
:Ca(OH)2
C6H2OH2ONO
:C6(H2O)2NO
C6H2NO2NO2NO2CH3OHOH
:C6H2(NO2)3CH3(OH)2
答案 4 :(得分:0)
以下是使用Map
&amp;的另一种解决方案。 ArrayList
代替regex
。
我将每个分子插入Map
并在每次出现在公式中时增加其键值,并使用ArrayList
来维持分子的顺序。
public static void main(String [] audi){
String s="C66H2NO2NO2NO2CH3";
Map<String, Integer > Formula=new HashMap<String, Integer >();
List E = new ArrayList();
String t="";int c=0,l=s.length();
for(int i=0;i<l;i++)
{
t=t.concat(""+s.charAt(i));
if(Character.isDigit(s.charAt(i)))
{
if(((i+1)<l && !Character.isDigit(s.charAt(i+1)) )|| i==l-1)
{
int count = Formula.containsKey(t) ? Formula.get(t) : 0;
Formula.put(t, count + 1);
if(!E.contains(t))
E.add(t);
t="";
}
}
}
//display
for(int i=0;i<E.size();i++){
if(Formula.get(E.get(i))>1)
System.out.print("("+E.get(i) + ")"+Formula.get(E.get(i)));
else
System.out.print(E.get(i));
}
}
输出: C6H2(NO2)3CH3