I have a simple formatted String:
double d = 12.348678;
int i = 9876;
String s = "ABCD";
System.out.printf("%08.2f%5s%09d", d, s, i);
// %08.2f = '12.348678' -> '00012,35'
// %5s = 'ABCD' -> ' ABCD'
// %09d = '9876' -> '000009876'
// %08.2f%5s%09d = '00012,35 ABCD000009876'
When i know the pattern: %08.2f%5s%09d and String: 00012,35 ABCD000009876:
Can i "unformat" this String in some way?
eg. the expected result something like 3 tokens: '00012,35', ' ABCD', '000009876'
This is specific to your pattern. A general parser for a formatstring, (because what we call unformatting is parsing) would look much different.
public class Unformat {
public static Integer getWidth(Pattern pattern, String format) {
Matcher matcher = pattern.matcher(format);
if (matcher.find()) {
return Integer.valueOf(matcher.group(1));
}
return null;
}
public static String getResult(Pattern p, String format, String formatted,
Integer start, Integer width) {
width = getWidth(p, format);
if (width != null) {
String result = formatted.substring(start, start + width);
start += width;
return result;
}
return null;
}
public static void main(String[] args) {
String format = "%08.2f%5s%09d";
String formatted = "00012.35 ABCD000009876";
String[] formats = format.split("%");
List<String> result = new ArrayList<String>();
Integer start = 0;
Integer width = 0;
for (int j = 1; j < formats.length; j++) {
if (formats[j].endsWith("f")) {
Pattern p = Pattern.compile(".*([0-9])+\\..*f");
result.add(getResult(p, formats[j], formatted, start, width));
} else if (formats[j].endsWith("s")) {
Pattern p = Pattern.compile("([0-9])s");
result.add(getResult(p, formats[j], formatted, start, width));
} else if (formats[j].endsWith("d")) {
Pattern p = Pattern.compile("([0-9])d");
result.add(getResult(p, formats[j], formatted, start, width));
}
}
System.out.println(result);
}
}
Judging by your output format of "%08.2f%5s%09d", it seems comparable to this pattern
"([0-9]{5,}[\\.|,][0-9]{2,})(.{5,})([0-9]{9,})"
Try the following:
public static void main(String[] args) {
String data = "00012,35 ABCD000009876";
Matcher matcher = Pattern.compile("([0-9]{5,}[\\.|,][0-9]{2,})(.{5,})([0-9]{9,})").matcher(data);
List<String> matches = new ArrayList<>();
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
matches.add(matcher.group(i));
}
}
System.out.println(matches);
}
Results:
[00012,35, ABCD, 000009876]
UPDATE
After seeing the comments, here's a generic example without using RegularExpressions as to not copy #bpgergo (+1 to you with generic RegularExpressions approach). Also added some logic in case the format ever exceeded the width of the data.
public static void main(String[] args) {
String data = "00012,35 ABCD000009876";
// Format exceeds width of data
String format = "%08.2f%5s%09d%9s";
String[] formatPieces = format.replaceFirst("^%", "").split("%");
List<String> matches = new ArrayList();
int index = 0;
for (String formatPiece : formatPieces) {
// Remove any argument indexes or flags
formatPiece = formatPiece.replaceAll("^([0-9]+\\$)|[\\+|-|,|<]", "");
int length = 0;
switch (formatPiece.charAt(formatPiece.length() - 1)) {
case 'f':
if (formatPiece.contains(".")) {
length = Integer.parseInt(formatPiece.split("\\.")[0]);
} else {
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
}
break;
case 's':
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
break;
case 'd':
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
break;
}
if (index + length < data.length()) {
matches.add(data.substring(index, index + length));
} else {
// We've reached the end of the data and need to break from the loop
matches.add(data.substring(index));
break;
}
index += length;
}
System.out.println(matches);
}
Results:
[00012,35, ABCD, 000009876]
You can do something like this:
//Find the end of the first value,
//this value will always have 2 digits after the decimal point.
int index = val.indexOf(".") + 3;
String tooken1 = val.substring(0, index);
//Remove the first value from the original String
val = val.substring(index);
//get all values after the last non-numerical character.
String tooken3 = val.replaceAll(".+\\D", "");
//remove the previously extracted value from the remainder of the original String.
String tooken2 = val.replace(tooken3, "");
This will fail if the String value contains a number at the end and probably in some other cases.
As you know the pattern, it means that you are dealing with some kind of regular expression. Use them to utilize your needs.
Java has decent regular expression API for such tasks
Regular expressions can have capturing groups and each group would have a single "unformatted" part just as you want. All depends on regex you will use/create.
Easiest thing to do would be to parse the string using a regex with myString.replaceAll(). myString.split(",") may also be helpful for splitting your string into a string array
Related
I have this number: 4200000000000000
I would like to leave only the first 4 digits and last 3 digits:
42000......000
Everything else should be replaced by dots. How I can implement this with some smart algorithm?
Why not use a StringBuilder and the substring method:
public static String foo(long num) {
String numToString = String.valueOf(num);
return new StringBuilder()
.append(numToString.substring(0 , 4))
.append("....")
.append(numToString.substring(numToString.length()-3, numToString.length()))
.toString();
}
When inputted 4200000000000000 it outputs:
4200....000
Or if the input is already a String:
public static String foo(String str) {
return new StringBuilder()
.append(str.substring(0 , 4))
.append("....")
.append(str.substring(str.length()-3, str.length()))
.toString();
}
Parse your number into a string and try this:
int last = 3;
int first = 4;
String number = '4200000000000000';
String start = number.substring(0,first-1);
String end = number.substring(number.length()-last,number.length()-1);
String dots = '';
for(int i = 0; i<number.length()-last-first;i++){
dots = dots + '.';
}
String result = start + dots + end;
You can use something like this,
public class Main {
public static void main(String[] args) {
System.out.println(convert("4200000000000000", 4, 3));
}
static String convert(String number, int firstDigits, int lastDigits) {
String first = number.substring(0, firstDigits);
String middle = number.substring(firstDigits, number.length() - lastDigits).replaceAll("0", ".");
String last = number.substring(number.length() - lastDigits, number.length());
return first + middle + last;
}
}
You could convert it to a char array, alter it, then convert it back into a string
char[] charArray = originalNumber.toCharArray();
for (int i; i < charArray.length; i++) {
if (i <= 4 || i >= charArray.length - 3) {
charArray[i] = ".";
}
}
String outputString = new String(charArray);
This will replace all chars from the 4th char up to the 4th from the end with '.':
String start = "4200000000000000";
System.out.println(start);
String target = start;
if (start.length() > 7) {
target = new StringBuilder()
.append(start.substring(0, 4))
.append(new String(new char[start.length() - 7]).replaceAll(".", "."))
.append(start.substring(start.length() - 3))
.toString();
}
System.out.println(target);
will print
4200000000000000
4200.........000
Using substring method of the String class :
String str = "4200000000000000";
String res = str.substring(0,4)+ str.substring(4,str.length()-3).replaceAll(".", ".") + str.substring(str.length()-3);
If you are using Apache commons library, you can use repeat method to create masking string of specified length and the overlay method of StringUtils class to overlay part of the String :
String str = "4200000000000000";
String mask= StringUtils.repeat('.', str.length()-7);
String res = StringUtils.overlay(str, mask, 4, str.length()-3);
I have a string which looks something like this(the most basic form):
String str = "1.0.0.190"
The str can be something like this as well:
1.11.0.12 or 2.111.1.190 or 1.0.0.0
I want to split the string at the 2nd occurrence of the dot(.). How can I achieve that ?
Output:
String str = "1.0.0.190"
String output = "1.0"
I'd fit the answer to OP's level, so I wouldn't recommend split or regexps to him...
If you need substring to second dot, simply find second dot and cut the string to that position...
public class DotSubstring {
public static void main(String[] args) {
String s = "1.2.3.4";
int secondDotPosition = findSecondDotPosition(s);
if (secondDotPosition > 0) {
System.out.println(s.substring(0, secondDotPosition));
} else {
System.out.printf("ERROR: there is not a 2nd dot in '%s'%n", s);
}
}
private static int findSecondDotPosition(String s) {
int result = -1;
int dotsToFind = 2;
char[] ca = s.toCharArray();
for (int i = 0; i < ca.length; ++i) {
if (ca[i] == '.') --dotsToFind;
if (dotsToFind == 0) return i;
}
return result;
}
}
The problem with split for beginner is, that is accepts regexp, that's why it is escaped in Joop Eggen's answe like this str.split("\\.").
And yes, that can be achieved in one line as user3458271 wrote in a comment same as xyz later in answer, just error checking would be more difficult (for example if there are no 2 dots...).
In one line with substring and indexOf:
String output = str.substring(0,str.indexOf(".",str.indexOf(".")+1));
public static void main(String[] args) {
String input = "2.111.1.190";
String[] out = input.split("\\.");
String output1 = out[0]+"."+out[1];
System.out.println(output1);
String output2 = "";
for(int x=2; x < out.length; x++)
output2 += out[x] +".";
System.out.println(output2);
}
For the other fields too:
String[] halfs = str.split("\\.");
String[] fulls = new String[halfs.length / 2];
for (int i = 0; i < fulls.length; ++i) {
fulls[i] = halfs[2*i] + "." + halfs[2*i + 1];
}
return fulls[0];
The same technique reduced for the first field:
String[] halfs = str.split("\\.", 3);
return halfs[0] + "." + halfs[1];
Simply:
return str.replaceAll("^([^.]*\\.[^.]*)\\..*$", "$1");
I want to split a String into n number of characters.
Consider input to be "Example-for-my-Question". Now if I want to split into n=3 characters, output should be "Exa, mpl, e-f, or-, my-, Que, sti, on" and suppose n=4, output should be "Exam, ple-, for-, my-Q, uest, ion" How can you modify the program below without using POSIX.
import java.util.Scanner;
public class SplitString {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter a String; ");
String inputString = in.nextLine();
System.out.println("How many characters do you want to split into ?");
int n = in.nextInt();
String[] array = inputString.split(" ", n);
System.out.println("Number of words: " + array.length);
for (String arr : array)
System.out.println(arr);
}
}
The simple way to do this is to use String.substring(...) repeatedly to trim N characters off the front of your string ... in a loop.
But if you really want to do this using String.split(...), then I think that the separator regex needs to be a positive look-behind that matches N characters. (It is obscure, and inefficient ... but if regexes are your universal tool ...)
You can use substring for this task.
String sp="StackOverFlow";
int NoOfChars=3;
for(int i=0;i<sp.length();i+=NoOfChars)
{
if(i+NoOfChars<=sp.length())
System.out.println(sp.substring(i,i+NoOfChars));
//Instead add in String ArrayList
else
System.out.println(sp.substring(i));
}
OUTPUT
Sta
ckO
ver
Flo
w
NOTE:Better to use trim() to remove leading or trailing spces
This works for me. In addition to splitting into known lengths, it checks for a null or "too small of a" source string, etc. If a null string is supplied, then a null is returned. If the source string is smaller than the requested split length, then the source string is simply returned.
public static void main (String[] args) throws java.lang.Exception
{
// Three test cases...
String pieces[] = SplitString("Example-for-my-Question", 3);
//String pieces[] = SplitString("Ex", 3);
//String pieces[] = SplitString(null, 3);
if (null != pieces)
{
for (int i = 0; i < pieces.length; i++)
{
System.out.println(pieces[i]);
}
}
}
private static String[] SplitString(String source, int size)
{
String result[] = null;
if (null != source && source.length() > size)
{
int numberOfElements = source.length() / size;
int modulo = source.length() % size;
if (modulo > 0)
{
numberOfElements++;
}
result = new String[numberOfElements];
for (int i = 0; i < numberOfElements; i++)
{
if (numberOfElements - 1 != i)
{
result[i] = source.substring(i * size, (i * size) + size);
}
else
{
result[numberOfElements - 1] = source.substring(i * size, (i * size) + modulo);
}
}
}
else if (null != source)
{
result = new String[1];
result[0] = source;
}
return result;
}
Please try the following program, but here you have to give input to "N" inside the program itself
class Main {
public static void main(String[] args) {
int N = 5;
String text = "aaaaabbbbbccccceeeeefff";
String[] tokens = text.split("(?<=\\G.{" + N + "})");
for(String t : tokens) {
System.out.println(t);
}
}
}
I did not find anywhere an answer.. If i have: String s = "How are you"?
How can i split this into two strings, so first string containing from 0..s.length()/2 and the 2nd string from s.length()/2+1..s.length()?
Thanks!
This should do:
String s = "How are you?";
String first = s.substring(0, s.length() / 2); // gives "How ar"
String second = s.substring(s.length() / 2); // gives "e you?"
String.substring(int i) with one argument returns the substring beginning at position i
String.substring(int i, int j) with two arguments returns the substring beginning at i and ending at j-1.
(Note that if the length of the string is odd, second will have one more character than first due to the rounding in the integer division.)
String s0 = "How are you?";
String s1 = s0.subString(0, s0.length() / 2);
String s2 = s0.subString(s0.length() / 2);
So long as s0 is not null.
EDIT
This will work for odd length strings as you are not adding 1 to either index. Surprisingly it even works on a zero length string "".
You can use 'substring(start, end)', but of course check if string isn't null before:
String first = s.substring(0, s.length() / 2);
String second = s.substring(s.length() / 2);
http://www.roseindia.net/java/beginners/SubstringExample.shtml
And are you expecting string with odd length ? in this case you must add logic to handle this case correctly.
Here's a method that splits a string into n items by length. (If the string length can not exactly be divided by n, the last item will be shorter.)
public static String[] splitInEqualParts(final String s, final int n){
if(s == null){
return null;
}
final int strlen = s.length();
if(strlen < n){
// this could be handled differently
throw new IllegalArgumentException("String too short");
}
final String[] arr = new String[n];
final int tokensize = strlen / n + (strlen % n == 0 ? 0 : 1);
for(int i = 0; i < n; i++){
arr[i] =
s.substring(i * tokensize,
Math.min((i + 1) * tokensize, strlen));
}
return arr;
}
Test code:
/**
* Didn't use Arrays.toString() because I wanted to have quotes.
*/
private static void printArray(final String[] arr){
System.out.print("[");
boolean first = true;
for(final String item : arr){
if(first) first = false;
else System.out.print(", ");
System.out.print("'" + item + "'");
}
System.out.println("]");
}
public static void main(final String[] args){
printArray(splitInEqualParts("Hound dog", 2));
printArray(splitInEqualParts("Love me tender", 3));
printArray(splitInEqualParts("Jailhouse Rock", 4));
}
Output:
['Hound', ' dog']
['Love ', 'me te', 'nder']
['Jail', 'hous', 'e Ro', 'ck']
Use String.substring(int), and String.substring(int, int) method.
int cutPos = s.length()/2;
String s1 = s.substring(0, cutPos);
String s2 = s.substring(cutPos, s.length()); //which is essentially the same as
//String s2 = s.substring(cutPos);
I did not find anywhere an answer.
The first place you should always look is at the javadocs for the class in question: in this case java.lang.String. The javadocs
can be browsed online on the Oracle website (e.g. at http://download.oracle.com/javase/6/docs/api/),
are included in any Sun/Oracle Java SDK distribution,
are probably viewable in your Java IDE, and
and be found using a Google search.
public int solution(final String S, final int K) {
int splitCount = -1;
final int count = (int) Stream.of(S.split(" ")).filter(v -> v.length() > K).count();
if (count > 0) {
return splitCount;
}
final List<String> words = Stream.of(S.split(" ")).collect(Collectors.toList());
final List<String> subStrings = new ArrayList<>();
int counter = 0;
for (final String word : words) {
final StringJoiner sj = new StringJoiner(" ");
if (subStrings.size() > 0) {
final String oldString = subStrings.get(counter);
if (oldString.length() + word.length() <= K - 1) {
subStrings.set(counter, sj.add(oldString).add(word).toString());
} else {
counter++;
subStrings.add(counter, sj.add(word).toString());
}
} else {
subStrings.add(sj.add(word).toString());
}
}
subStrings.forEach(
v -> {
System.out.printf("[%s] and length %d\n", v, v.length());
}
);
splitCount = subStrings.size();
return splitCount;
}
public static void main(final String[] args) {
final MessageSolution messageSolution = new MessageSolution();
final String message = "SMSas5 ABC DECF HIJK1566 SMS POP SUV XMXS MSMS";
final int maxSize = 11;
System.out.println(messageSolution.solution(message, maxSize));
}
I have a string that contains multiple parameters delimited by #, like this :
.... #param1# ... #param2# ... #paramN# ...
And I want to replace the parameter placeholders by values.
The current algorithm looks like this:
//retrieve place holder into this SQL select
Pattern p = Pattern.compile(DIMConstants.FILE_LINE_ESCAPE_INDICATOR);
Matcher m = p.matcher(sqlToExec); // get a matcher object
int count = 0;
int start = 0;
int end = 0;
StringBuilder params = new StringBuilder();
while (m.find()) {
count++;
if (count % 2 == 0) {
// Second parameter delimiter
String patternId = sqlToExec.substring(start, m.end());
//Clean value (#value#->value)
String columnName = patternId.substring(1, patternId.length() - 1);
//Look for this column into preLoad row ResultSet and retrieve its value
String preLoadTableValue = DIMFormatUtil.convertToString(sourceRow.get(columnName));
if (!StringUtils.isEmpty(preLoadTableValue)) {
aSQL.append(loadGemaDao.escapeChars(preLoadTableValue).trim());
} else {
aSQL.append(DIMConstants.COL_VALUE_NULL);
}
params.append(" " + columnName + "=" + preLoadTableValue + " ");
end = m.end();
} else {
// First parameter delimiter
start = m.start();
aSQL.append(sqlToExec.substring(end, m.start()));
}
}
if (end < sqlToExec.length()) {
aSQL.append(sqlToExec.substring(end, sqlToExec.length()));
}
I'm looking for a simplest solution, using regexp or another public API. Input parameters will be the source string, a delimiter and a map of values. Output parameter will be the source string with all the parameters replaced.
If this is for a normal SQL query, you might want to look into using PreparedStatements
Beyond that, am I missing something? Why not just use String.replace()? Your code could look like this:
for(int i = 0; i < n; i++){
String paramName = "#param" + i + "#"
sqlToExec = sqlToExec.replace(paramName,values.get(paramName));
}
That assumes you have a map called "values" with string mappings between parameters in the form "#paramN#"
If you need it more generic, this will find and return the whole param including the #'s:
public class ParamFinder {
public static void main(String[] args) {
String foo = "#Field1# #Field2# #Field3#";
Pattern p = Pattern.compile("#.+?#");
Matcher m = p.matcher(foo);
List matchesFound = new ArrayList();
int ndx = 0;
while(m.find(ndx)){
matchesFound.add(m.group());
ndx = m.end();
}
for(Object o : matchesFound){
System.out.println(o);
}
}
}