package com.llamacorp.equate; import java.util.ArrayList; public class ExpSeparatorHandler { private static String THOUS_SEP = ","; public ArrayList<Integer> mSepIndexes; public ExpSeparatorHandler() { mSepIndexes = new ArrayList<>(); } /** * Inserts separators between thousands places in a String representation * of a expression composed of numbers and other characters. Ignores * numbers after a decimal point or "E". * * @param str String representation of expression to add separators to * @return String with separators added: eg 1000 returns 1,000; 1420.2425+53 * returns 1,420.2425+53; */ static public String addSep(String str) { return getSepTextHelper(str, null); } /** * Static method that just removes separators from a given string * * @param str is the string with separators * @return the str with separators removed */ static public String removeSep(String str) { return str.replace(THOUS_SEP, ""); } /** * Inserts separators between thousands places in a String representation * of a expression composed of numbers and other characters. Ignores * numbers after a decimal point or "E". Keeps track of each added * seperator's index. * * @param str String representation of expression to add separators to * @return String with separators added: eg 1000 returns 1,000; 1420.2425+53 * returns 1,420.2425+53; */ public String getSepText(String str) { return getSepTextHelper(str, mSepIndexes); } static private String getSepTextHelper(String str, ArrayList<Integer> indList) { if (indList != null) indList.clear(); final String regNum = "\\d"; final String regSkipNumsAfter = "[E.]"; int numCount = 0; for (int i = 0; i <= str.length(); i++) { //check to see if this isn't the last try and we have a number if (i < str.length() && str.substring(i, i + 1).matches(regNum)) numCount++; //we have a number, increment counter else { //insert commas if (numCount > 3){ for (int j = numCount % 3; j < numCount; j = j + 3) { if (j == 0) continue; int comPos = i - numCount + j; str = str.substring(0, comPos) + THOUS_SEP + str.substring(comPos, str.length()); if (indList != null) indList.add(comPos); i++; //offset for added commas } } //we're at the end of the string and finished inserted commas, leave if (i == str.length()) break; //skip over numbers directly following decimals (or E) if (str.substring(i, i + 1).matches(regSkipNumsAfter)){ do { i++; } while (i != str.length() && str.substring(i, i + 1).matches(regNum)); } numCount = 0; } } return str; } /** * Same as translateToSepIndex, except for list of indexes */ public ArrayList<Integer> translateIndexListToSep(ArrayList<Integer> inList) { ArrayList<Integer> outList = new ArrayList<>(); for (int i = 0; i < inList.size(); i++) outList.add(i, translateToSepIndex(inList.get(i))); return outList; } /** * Takes and index in the current sequence of numbers (the last call to * getSepText sets the sequence) without separators and moves it to the * same location relative to the number's digits (ignoring the * separators. Eg given index=2 for exp=1,234; outputs 3 */ public int translateToSepIndex(int index) { if (mSepIndexes == null) return index; else for (int i = 0; i < mSepIndexes.size(); i++) if (mSepIndexes.get(i) < index) index++; return index; } /** * Takes and index in the current sequence of numbers (the last call to * getSepText sets the sequence) with separators and moves it to the * same location relative to the number's digits (ignoring the * separators. Eg given index=3 for exp=1,234; outputs 2 */ public int translateFromSepIndex(int index) { if (mSepIndexes == null) return index; int numSmaller = 0; for (int i = 0; i < mSepIndexes.size(); i++) if (mSepIndexes.get(i) < index) numSmaller++; return index - numSmaller; } /** * Take an index and shift it over if it's in an invalid location relative * to the separator. Eg if index=2 in 1,234, move it to 1 */ public int makeIndexValid(int index) { if (mSepIndexes != null) for (int i = 0; i < mSepIndexes.size(); i++) if (mSepIndexes.get(i) + 1 == index) index--; return index; } }