I need to convert Arabic/Persian Numbers to its English equal (for example convert "۲" to "2")
How can I do this?
I suggest you have a ten digit lookup String and replace all the digits one at a time.
public static void main(String... args) {
System.out.println(arabicToDecimal("۴۲"));
}
//used in Persian apps
private static final String extendedArabic = "\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9";
//used in Arabic apps
private static final String arabic = "\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669";
private static String arabicToDecimal(String number) {
char[] chars = new char[number.length()];
for(int i=0;i<number.length();i++) {
char ch = number.charAt(i);
if (ch >= 0x0660 && ch <= 0x0669)
ch -= 0x0660 - '0';
else if (ch >= 0x06f0 && ch <= 0x06F9)
ch -= 0x06f0 - '0';
chars[i] = ch;
}
return new String(chars);
}
prints
42
The reason for using the strings as a lookup is that other characters such as . - , would be left as is. In fact a decimal number would be unchanged.
I achived this by java.math.BigDecimal Class, Below is the code snippet
String arabicNumerals = "۴۲۴۲.۴۲";
String englishNumerals = new BigDecimal(arabic).toString();
System.out.println("Number In Arabic : "+arabicNumerals);
System.out.println("Number In English : "+englishNumerals);
Result
Number In Arabic : ۴۲۴۲.۴۲
Number In English : 4242.42
NB: The above code will not work if there are any characteors other than numeric digits in arabicNumerals, for example: ۴,۲۴۲.۴۲ will result in a java.lang.NumberFormatException, so you may remove other characters using Character.isDigit(char ch) in another logic and use the above code. All normal cases are working.
I found a simpler and faster way which includes the two arabic code pages too.
public static String convertToEnglishDigits(String value)
{
String newValue = value.replace("١", "1").replace("٢", "2").replace("٣", "3").replace("٤", "4").replace("٥", "5")
.replace("٦", "6").replace("7", "٧").replace("٨", "8").replace("٩", "9").replace("٠", "0")
.replace("۱", "1").replace("۲", "2").replace("۳", "3").replace("۴", "4").replace("۵", "5")
.replace("۶", "6").replace("۷", "7").replace("۸", "8").replace("۹", "9").replace("۰", "0");
return newValue;
}
It will return the numbers in English format or vise versa if you change the replace from.
("۰", "0") to ("0","۰")
Try this guys:
/**
* Utility class to detect arabic languages and convert numbers into arabic digits.
*
* #author Ahmed Shakil
* #date 09-24-2012
*/
public final class ArabicUtil {
private static final char[] DIGITS = {'\u0660','\u0661','\u0662','\u0663','\u0664','\u0665','\u0666','\u0667','\u0668','\u0669'};
/**
* Returns <code>true</code> if the provided language code uses arabic characters; othersise <code>false</code>.
* #param lang ISO language code.
* #return <code>true</code> if the provided language code uses arabic characters; othersise <code>false</code>
*/
public static boolean isArabic (String lang) {
return "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang);
}
/**
* Convert digits in the specified string to arabic digits.
*/
public static String convertDigits (String str) {
if (str == null || str.length() == 0) return str;
char[] s = new char[str.length()];
for(int i =0;i<s.length;i++)
s[i] = toDigit( str.charAt( i ) );
return new String(s);
}
/**
* Convert single digit in the specified string to arabic digit.
*/
public static char toDigit (char ch) {
int n = Character.getNumericValue( (int)ch );
return n >=0 && n < 10 ? ARABIC[n] : ch;
}
/**
* Convert an int into arabic string.
*/
public static String toString (int num) {
return convertDigits( Integer.toString( num ) );
}
}
BTW there is a difference between arabic digits vs. urdu/farsi:
Arabic:
private static final char[] ARABIC = {'\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668', '\u0669'};
Urdu or Farsi:
private static final char[] URDU_FARSI = {'\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8', '\u06f9'};
First make it work, then make it look nice ;-)
public static char persianDigitToEnglish(char persianDigit) {
return (char) (((int)persianDigit) - ((int)'۲' - (int)'2'));
}
Works for 2, unfortunately I don't know other Persian digits, could You give it a try?
assertThat(persianDigitToEnglish('۲')).isEqualTo('2');
EDIT: (based on Peter Lawrey String version, but uses StringBuilder)
public static String persianDigitToEnglish(String persianNumber) {
StringBuilder chars = new StringBuilder(persianNumber.length());
for (int i = 0; i < persianNumber.length(); i++)
chars.append(persianDigitToEnglish(persianNumber.charAt(i)));
return chars.toString();
}
private static char persianDigitToEnglish(char persianDigit) {
return (char) (((int)persianDigit) - ((int)'۲' - (int)'2'));
}
so trivial answer:
public static String convertNumbersToPersian(String str)
{
String answer = str;
answer = answer.replace("1","١");
answer = answer.replace("2","٢");
answer = answer.replace("3","٣");
answer = answer.replace("4","٤");
answer = answer.replace("5","٥");
answer = answer.replace("6","٦");
answer = answer.replace("7","٧");
answer = answer.replace("8","٨");
answer = answer.replace("9","٩");
answer = answer.replace("0","٠");
return answer;
}
and
public static String convertNumbersToEnglish(String str) {
String answer = str;
answer = answer.replace("١", "1");
answer = answer.replace("٢", "2");
answer = answer.replace("٣", "3");
answer = answer.replace("٤", "4");
answer = answer.replace("٥", "5");
answer = answer.replace("٦", "6");
answer = answer.replace("٧", "7");
answer = answer.replace("٨", "8");
answer = answer.replace("٩", "9");
answer = answer.replace("٠", "0");
return answer;
}
Character.getNumericValue(ch) saved my life, generic solution for any locale.
static String replaceNonstandardDigits(String input) {
if (input == null || input.isEmpty()) {
return input;
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (Character.isDigit(ch) && !(ch >= '0' && ch <= '9')) {
int numericValue = Character.getNumericValue(ch);
if (numericValue >= 0) {
builder.append(numericValue);
}
} else {
builder.append(ch);
}
}
return builder.toString();
}
i think the best way is to change the Locale to what you want for example,
for double number :
NumberFormat fmt = NumberFormat.getNumberInstance(Locale.US);
d = Double.parseDouble(s);
for String :
NumberFormat.getNumberInstance(Locale.US).format(s);
or DecimalFormat:
double num;
DecimalFormat df = new DecimalFormat("###.###");
df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
String s = df.format(num);
While I was looking for the most performant solution I mixed Kishath and Sileria answers and came up with a clean and fast result:
public class StringLocalizer {
private static final char[] ENGLISH_NUMBERS = {'\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037', '\u0038', '\u0039'};
private static final char[] PERSIAN_NUMBERS = {'\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8', '\u06f9'};
private static final char[] ARABIC_NUMBERS = {'\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668', '\u0669'};
public static String on(String input) {
String lang = Locale.getDefault().getLanguage();
boolean isPersian = "fa".equals(lang) || "ur".equals(lang);
boolean isArabic = "ar".equals(lang);
if (isPersian) return input
.replace(ENGLISH_NUMBERS[0], PERSIAN_NUMBERS[0])
.replace(ENGLISH_NUMBERS[1], PERSIAN_NUMBERS[1])
.replace(ENGLISH_NUMBERS[2], PERSIAN_NUMBERS[2])
.replace(ENGLISH_NUMBERS[3], PERSIAN_NUMBERS[3])
.replace(ENGLISH_NUMBERS[4], PERSIAN_NUMBERS[4])
.replace(ENGLISH_NUMBERS[5], PERSIAN_NUMBERS[5])
.replace(ENGLISH_NUMBERS[6], PERSIAN_NUMBERS[6])
.replace(ENGLISH_NUMBERS[7], PERSIAN_NUMBERS[7])
.replace(ENGLISH_NUMBERS[8], PERSIAN_NUMBERS[8])
.replace(ENGLISH_NUMBERS[9], PERSIAN_NUMBERS[9]);
else if (isArabic) return input
.replace(ENGLISH_NUMBERS[0], ARABIC_NUMBERS[0])
.replace(ENGLISH_NUMBERS[1], ARABIC_NUMBERS[1])
.replace(ENGLISH_NUMBERS[2], ARABIC_NUMBERS[2])
.replace(ENGLISH_NUMBERS[3], ARABIC_NUMBERS[3])
.replace(ENGLISH_NUMBERS[4], ARABIC_NUMBERS[4])
.replace(ENGLISH_NUMBERS[5], ARABIC_NUMBERS[5])
.replace(ENGLISH_NUMBERS[6], ARABIC_NUMBERS[6])
.replace(ENGLISH_NUMBERS[7], ARABIC_NUMBERS[7])
.replace(ENGLISH_NUMBERS[8], ARABIC_NUMBERS[8])
.replace(ENGLISH_NUMBERS[9], ARABIC_NUMBERS[9]);
else return input
.replace(PERSIAN_NUMBERS[0], ENGLISH_NUMBERS[0])
.replace(PERSIAN_NUMBERS[1], ENGLISH_NUMBERS[1])
.replace(PERSIAN_NUMBERS[2], ENGLISH_NUMBERS[2])
.replace(PERSIAN_NUMBERS[3], ENGLISH_NUMBERS[3])
.replace(PERSIAN_NUMBERS[4], ENGLISH_NUMBERS[4])
.replace(PERSIAN_NUMBERS[5], ENGLISH_NUMBERS[5])
.replace(PERSIAN_NUMBERS[6], ENGLISH_NUMBERS[6])
.replace(PERSIAN_NUMBERS[7], ENGLISH_NUMBERS[7])
.replace(PERSIAN_NUMBERS[8], ENGLISH_NUMBERS[8])
.replace(PERSIAN_NUMBERS[9], ENGLISH_NUMBERS[9])
.replace(ARABIC_NUMBERS[0], ENGLISH_NUMBERS[0])
.replace(ARABIC_NUMBERS[1], ENGLISH_NUMBERS[1])
.replace(ARABIC_NUMBERS[2], ENGLISH_NUMBERS[2])
.replace(ARABIC_NUMBERS[3], ENGLISH_NUMBERS[3])
.replace(ARABIC_NUMBERS[4], ENGLISH_NUMBERS[4])
.replace(ARABIC_NUMBERS[5], ENGLISH_NUMBERS[5])
.replace(ARABIC_NUMBERS[6], ENGLISH_NUMBERS[6])
.replace(ARABIC_NUMBERS[7], ENGLISH_NUMBERS[7])
.replace(ARABIC_NUMBERS[8], ENGLISH_NUMBERS[8])
.replace(ARABIC_NUMBERS[9], ENGLISH_NUMBERS[9]);
}
}
Note that here we assumed localizing is done between English and Persian or Arabic, so if you also need to include another language in replacing criteria just add the missing replace clauses.
This code will work with decimal points also:
public class mainsupport {
public static void main(String args[]){
// String Numtoconvert="15.3201" ;
// String Numtoconvert="458" ;
String Numtoconvert="٨٧٫٥٩٨" ; // integer value 87.598
System.out.println(getUSNumber(Numtoconvert));
}
private static String getUSNumber(String Numtoconvert){
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
try {
if(Numtoconvert.contains("٫"))
Numtoconvert=formatter.parse(Numtoconvert.split("٫")[0].trim())+"."+formatter.parse(Numtoconvert.split("٫")[1].trim());
else
Numtoconvert=formatter.parse(Numtoconvert).toString();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Numtoconvert;
}
This prints 87.598.
The following seems to me to be the simple and obvious solution. I don’t know why it hasn’t been posted before.
Locale persian = Locale.forLanguageTag("fa");
NumberFormat nf = NumberFormat.getIntegerInstance(persian);
String persianIntegerString = "۲۱";
int parsedInteger = nf.parse(persianIntegerString).intValue();
System.out.println(parsedInteger);
Output is:
21
If we’ve got a string with a decimal point in it (or just one that may have that), use getInstance instead of getIntegerInstance. At the same time I am taking an Arabic string this time to demonstrate that this works too.
Locale arabic = Locale.forLanguageTag("ar");
NumberFormat nf = NumberFormat.getInstance(arabic);
String arabicDecimalString = "٣٤٫٥٦";
double parsedDouble = nf.parse(arabicDecimalString).doubleValue();
System.out.println(parsedDouble);
34.56
In many cases the number formats can also parse numbers in other locales, but I doubt that it is always the case, so I would not want to rely on it.
Use Locale class to convert numbers.
Locale locale = new Locale("ar");
String formattedArabic = format(locale, "%d", value));
Try this for converting Persian/Arabic numbers to English:
public static String convertToEnglish(String arabicNumber) {
for (int i = 0; i <= 9; i++) {
arabicNumber= arabicNumber.replace((char) (1776 + i),
(char) (48 + i));
}
return arabicNumber;
}
I think instead of replacing the digits one by one (which would only work for decimal numbers), you should parse your number with a persian NumberFormat to a number, and then (if necessary) use a english NumberFormat to format it again.
Related
This post is an update to this one : get specific character in a string with regex and remove unused zero
In the first place, i wanted to remove with an regular expression the unused zero in the last match.
I found that the regular expression is a bit overkill for what i need.
Here is what i would like now,
I would like to use split() method
to get from this :
String myString = "2020-LI50532-3329-00100"
this :
String data1 = "2020"
String data2 = "LI50532"
String data3 = "3329"
String data4 = "00100"
So then i can remove from the LAST data the unused Zero
to convert "00100" in "100"
And then concatenate all the data to get this
"2020-LI50532-3329-100"
Im not familiar with the split method, if anyone can enlight me about this ^^
You can use substring method to get rid of the leading zeros...
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + data[3]);
String result = sb.toString();
System.out.println(result);
Assuming that we want to remove the leading zeroes of ONLY the last block, maybe we can:
Extract the last block
Convert it to Integer and back to String to remove leading zeroes
Replace the last block with the String obtained in above step
Something like this:
public String removeLeadingZeroesFromLastBlock(String text) {
int indexOfLastDelimiter = text.lastIndexOf('-');
if (indexOfLastDelimiter >= 0) {
String lastBlock = text.substring(indexOfLastDelimiter + 1);
String lastBlockWithoutLeadingZeroes = String.valueOf(Integer.valueOf(lastBlock)); // will throw exception if last block is not an int
return text.substring(0, indexOfLastDelimiter + 1).concat(lastBlockWithoutLeadingZeroes);
}
return text;
}
Solution using regex:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
return str.replaceAll("0+(?=[1-9]\\d*$)", "");
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
Explanation of the regex:
One or more zeros followed by a non-zero digit which can be optionally followed by any digit(s) until the end of the string (specified by $).
Solution without using regex:
You can do it also by using Integer.parseInt which can parse a string like 00100 into 100.
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
String[] parts = str.split("-");
try {
parts[parts.length - 1] = String.valueOf(Integer.parseInt(parts[parts.length - 1]));
} catch (NumberFormatException e) {
// Do nothing
}
return String.join("-", parts);
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
you can convert the last string portion to integer type like below for removing unused zeros:
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + Integer.parseInt(data[3]));
String result = sb.toString();
System.out.println(result);
You should avoid String manipulation where possible and rely on existing types in the Java language. One such type is the Integer. It looks like your code consists of 4 parts - Year (Integer) - String - Integer - Integer.
So to properly validate it I would use the following code:
Scanner scan = new Scanner("2020-LI50532-3329-00100");
scan.useDelimiter("-");
Integer firstPart = scan.nextInt();
String secondPart = scan.next();
Integer thirdPart = scan.nextInt();
Integer fourthPart = scan.nextInt();
Or alternatively something like:
String str = "00100";
int num = Integer.parseInt(str);
System.out.println(num);
If you want to reconstruct your original value, you should probably use a NumberFormat to add the missing 0s.
The main points are:
Always try to reuse existing code and tools available in your language
Always try to use available types (LocalDate, Integer, Long)
Create your own types (classes) and use the expressiveness of the Object Oriented language
public class Test {
public static void main(String[] args) {
System.out.println(trimLeadingZeroesFromLastPart("2020-LI50532-03329-00100"));
}
private static String trimLeadingZeroesFromLastPart(String input) {
String delem = "-";
String result = "";
if (input != null && !input.isEmpty()) {
String[] data = input.split(delem);
StringBuilder tempStrBldr = new StringBuilder();
for (int idx = 0; idx < data.length; idx++) {
if (idx == data.length - 1) {
tempStrBldr.append(trimLeadingZeroes(data[idx]));
} else {
tempStrBldr.append(data[idx]);
}
tempStrBldr.append(delem);
}
result = tempStrBldr.substring(0, tempStrBldr.length() - 1);
}
return result;
}
private static String trimLeadingZeroes(String input) {
int idx;
for (idx = 0; idx < input.length() - 1; idx++) {
if (input.charAt(idx) != '0') {
break;
}
}
return input.substring(idx);
}
}
Output:
2020-LI50532-3329-100
I have a string in format AB123. I want to split it between the AB and 123 so AB123 becomes AB 123. The contents of the string can differ but the format stays the same. Is there a way to do this?
Following up with the latest information you provided (2 letters then 3 numbers):
myString.subString(0, 2) + " " + myString.subString(2)
What this does: you split your input string myString at the 2nd character and append a space at this position.
Explanation: \D represents non-digit and \d represents a digit in a regular expression and I used ternary operation in the regex to split charter to the number.
String string = "AB123";
String[] split = string.split("(?<=\\D)(?=\\d)");
System.out.println(split[0]+" "+split[1]);
Try
String a = "abcd1234";
int i;
for(i = 0; i < a.length(); i++){
char c = a.charAt(i);
if( '0' <= c && c <= '9' )
break;
}
String alphaPart = a.substring(0, i);
String numberPart = a.substring(i);
Hope this helps
Although I would personally use the method provided in #RakeshMothukur's answer, since it also works when the letter or digit counts increase/decrease later on, I wanted to provide an additional method to insert the space between the two letters and three digits:
String str = "AB123";
StringBuilder sb = new StringBuilder(str);
sb.insert(2, " "); // Insert a space at 0-based index 2; a.k.a. after the first 2 characters
String result = sb.toString(); // Convert the StringBuilder back to a String
Try it online.
Here you go. I wrote it in very simple way to make things clear.
What it does is : After it takes user input, it converts the string into Char array and it checks single character if its INT or non INT.
In each iteration it compares the data type with the prev character and prints accordingly.
Alternate Solutions
1) Using ASCII range (difficulty = easy)
2) Override a method and check 2 variables at a time. (difficulty = Intermediate)
import org.omg.CORBA.INTERNAL;
import java.io.InputStreamReader;
import java.util.*;
import java.io.BufferedReader;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char[] s = br.readLine().toCharArray();
int prevflag, flag = 0;
for (int i = 0; i < s.length; i++) {
int a = Character.getNumericValue(s[i]);
String b = String.valueOf(s[i]);
prevflag = flag;
flag = checktype(a, b);
if ((prevflag == flag) || (i == 0))
System.out.print(s[i]);
else
System.out.print(" " + s[i]);
}
}
public static int checktype(int x, String y) {
int flag = 0;
if (String.valueOf(x).equals(y))
flag = 1; // INT
else
flag = 2; // non INT
return flag;
}
}
I was waiting for a compile to finish before heading out, so threw together a slightly over-engineered example with basic error checking and a test.
import java.text.ParseException;
import java.util.LinkedList;
public class Main {
static public class ParsedData {
public final String prefix;
public final Integer number;
public ParsedData(String _prefix, Integer _number) {
prefix = _prefix;
number = _number;
}
#Override
public String toString() {
return prefix + "\t" + number.toString();
}
}
static final String TEST_DATA[] = {"AB123", "JX7272", "FX402", "ADF123", "JD3Q2", "QB778"};
public static void main(String[] args) {
parseDataArray(TEST_DATA);
}
public static ParsedData[] parseDataArray(String[] inputs) {
LinkedList<ParsedData> results = new LinkedList<ParsedData>();
for (String s : TEST_DATA) {
try {
System.out.println("Parsing: " + s);
if (s.length() != 5) throw new ParseException("Input Length incorrect: " + s.length(), 0);
String _prefix = s.substring(0, 2);
Integer _num = Integer.parseInt(s.substring(2));
results.add(new ParsedData(_prefix, _num));
} catch (ParseException | NumberFormatException e) {
System.out.printf("\"%s\", %s\n", s, e.toString());
}
}
return results.toArray(new ParsedData[results.size()]);
}
}
This question already has answers here:
Creating a UUID from a string with no dashes
(10 answers)
Closed 2 years ago.
I get UUIDs in the format like "005056963AB75FD48BDC59C100314C40" and want to validate them. I tried code like this:
public boolean isUUID(String uuid){
try {
UUID.fromString(uuid);
} catch (Exception e) {
return false;
}
return true;
}
But this will tell me that "005056963AB75FD48BDC59C100314C40" is not a valid ID. The site http://guid.us/Test/GUID on the other hand tells me it is and gives me back an UUID with the "-" added.
Is there an elegant way to validate this UUID in java or do I have to manually add "-" to the right places?
try regex
uuid = uuid.replaceAll("(.{8})(.{4})(.{4})(.{4})(.+)", "$1-$2-$3-$4-$5");
UUID.fromString(uuid);
You can use this Java regex code to put hyphens at right place in UUID string:
String s = "005056963AB75FD48BDC59C100314C40";
s = s.replaceAll(
"(?i)([a-f0-9]{8})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{12})",
"$1-$2-$3-$4-$5");
System.out.printf("UUID: [%s]%n", s);
//=> 00505696-3AB7-5FD4-8BDC-59C100314C40
Update: Non regex solution (thnks to #atamanroman)
StringBuilder sbr = new StringBuilder(s);
for(int i=8, j=0; i<=20; i+=4, j++)
sbr.insert(i+j, '-');
UUID uuid = UUID.fromString( sbr.toString() );
To add dashes to an UUID string, I would suggest to use StringBuilder#insert(int offset, chat c) as #atamanroman said.
final String uuid = new StringBuilder("005056963AB75FD48BDC59C100314C40")
.insert(20, '-')
.insert(16, '-')
.insert(12, '-')
.insert(8, '-')
.toString();
System.out.println(uuid);
This is an example of function that validates UUID strings without hyphens. It's faster because it doesn't use regexp or buffering. A UUID without hyphens is just a string of 32 hexadecimal chars.
public class Example1 {
/**
* Validate UUID without hyphens.
*
* #param uuid a uuid string
* #return true if valid
*/
public static boolean isValid(String uuid) {
if (uuid == null || uuid.length() != 32) {
return false;
}
final char[] chars = uuid.toCharArray();
for (int i = 0; i < chars.length; i++) {
final int c = chars[i];
if (!((c >= 0x30 && c <= 0x39) || (c >= 0x61 && c <= 0x66) || (c >= 0x41 && c <= 0x46))) {
// ASCII codes: 0-9, a-f, A-F
return false;
}
}
return true;
}
public static void main(String[] args) {
String uuid = "005056963AB75FD48BDC59C100314C40";
if(isValid(uuid)) {
// do something
}
}
}
You can also use UuidValidator.isValid() from the library uuid-creator. It validates UUID strings with or without hyphens. This is another example:
import com.github.f4b6a3.uuid.util.UuidValidator;
public class Example2 {
public static void main(String[] args) {
String uuid = "005056963AB75FD48BDC59C100314C40";
if(UuidValidator.isValid(uuid)) {
// do something
}
}
}
But if you just want to convert a string into a UUID, you can use UuidCreator.fromString(). This function also validates the input.
import java.util.UUID;
import com.github.f4b6a3.uuid.util.UuidValidator;
public class Example3 {
public static void main(String[] args) {
String uuidString = "005056963AB75FD48BDC59C100314C40";
UUID uuid = UuidCreator.fromString(uuidString);
}
}
Project page: https://github.com/f4b6a3/uuid-creator
I was given this problem to solve. I have only the slightest idea on how it should be implemented, and I'm all too new with programming and stuffs, and would love to hear your comments on this.
Say given a string in the form "abc1234defgh567jk89", and I must create a new string "a1b2c3d5e6f7j8k9".
Note that there are corresponding [digits] & [characters] group and since there may be more of one type over the other, the output has only matching sequence and ignore extra digits or characters in this case '4' & 'g' & 'h'.
I know I will have to use 2 sets of queues to store both types of elements, but I do not know how else to proceed from here.
Would appreciate if you could share a pseudocode or a Java(prefably) version, since I am learning thru this language now.
Thank you.
Pseudocode:
Queue letterQueue;
Queue numberQueue;
for (every character in the string) {
if (it's a letter) {
if (numberQueue is not empty) {
add the letters alternating into the buffer (stringbuilder), and purge buffers
}
add newest letter to letterqueue
}
if (it's a number) {
add newest letter to numberqueue
}
}
add any remaining unprocessed letters to the queue (this will happen most of the time)
return contents of string buffer
You will need:
Queue, probably a LinkedList
StringBuilder
String.toCharArray
Character
Code:
import java.util.LinkedList;
import java.util.Queue;
public class StringTest {
private static String str ="abc1234defgh567jk89";
private static String reorganize(String str) {
Queue<Character> letterQueue = new LinkedList<>();
Queue<Character> numberQueue = new LinkedList<>();
StringBuilder s = new StringBuilder();
for (char c : str.toCharArray()) {
if(Character.isLetter(c)) {
if (!numberQueue.isEmpty()) processQueues(letterQueue, numberQueue, s);
letterQueue.offer(c);
} else if(Character.isDigit(c)) {
numberQueue.offer(c);
}
}
processQueues(letterQueue, numberQueue, s);
return s.toString();
}
private static void processQueues(Queue<Character> letterQueue, Queue<Character> numberQueue, StringBuilder s) {
while(!letterQueue.isEmpty() && !numberQueue.isEmpty()) {
s.append(letterQueue.poll());
s.append(numberQueue.poll());
}
letterQueue.clear();
numberQueue.clear();
}
public static void main(String... args) {
System.out.println(reorganize(str));
}
}
See this hint:
String str = "abc1234defgh567jk89";
String c = str.replaceAll("\\d", ""); // to store characters
String d = str.replaceAll("\\D", ""); // to store digits
Try this:
public static void main(String[] args) {
String str = "abc1234defgh567jk89";
String c = str.replaceAll("\\d", "");
String d = str.replaceAll("\\D", "");
String result = "";
int j = 0, k = 0;
int max = Math.max(c.length(), d.length());
for (int i = 0; i < max; i++) {
if (j++ < c.length())
result = result + c.charAt(i);
if (k++ < d.length())
result = result + d.charAt(i);
}
System.out.println(result);
}
Output:
a1b2c3d4e5f6g7h8j9k
I have a number as a string like this: "9.756088256835938E-4" but I only can use a specified number of characters (in this special case 9 char). So I want to have something like this: "9.7561E-4". I already tried to convert the String to a Double and then used the format method to get a less characters but I don't got a correct solution.
The problem is that I need ten exponential output since some numbers are longer than the number of characters I have. If it is possible, the number should be displayed with no ten exponent, if not just use the ten exponent.
Also correct rounding would be good.
And it should work for negative numbers. (minus needs one character!!!)
Is there a format function where I can define the maximum length of the output string? Any ideas?
I'm having trouble findind a single format pattern that will cover all of the cases that you described. But here's a combination of logic that I think works:
public static void main(String[] args) throws Exception {
// 97.560883
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+1")));
// 9.756E+11
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+11")));
// 0.0009756
System.out.println(formatNum(Double.parseDouble("9.756088256835938E-4")));
// -9.8E+111
System.out.println(formatNum(Double.parseDouble("-9.756088256835938E+111")));
}
private static final int MAX_LENGTH = 9;
private static String formatNum(double number) {
String out = null;
for ( int i = 0; i < MAX_LENGTH; i++ ) {
String format = "%." + i + "G";
out = String.format(format, number);
if ( out.length() == MAX_LENGTH ) {
return out;
}
}
return out; //the best we can do
}
The "G" in the pattern instructs the formatter to forego the use of the exponent when it will allow for the same or better precision. We grow up to the maximum length and stop when our output string is 10 characters. I think you could take the same approach with a DecimalFormat, but I'm more familiar with Formatter.
Seeing the Mark's example meet your requirements, I updated my answer to show the DecimalFormat implementation. I used Mark's test cases. It is definitely an uglier option because there is no easy way to turn on/off exponents. The only advantage over the String.format option is that it handles very small numbers well.
public static void main(String[] args) throws Exception {
// 97.560883
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+1")));
// 9.756E+11
System.out.println(formatNum(Double.parseDouble("9.756088256835938E+11")));
// 0.0009756
System.out.println(formatNum(Double.parseDouble("9.756088256835938E-4")));
// -9.8E+111
System.out.println(formatNum(Double.parseDouble("-9.756088256835938E+111")));
}
private static final int MAX_LENGTH = 9;
private static String formatNum(double number) {
int digitsAvailable = MAX_LENGTH - 2;
if (Math.abs(number) < Math.pow(10, digitsAvailable)
&& Math.abs(number) > Math.pow(10, -digitsAvailable)) {
String format = "0.";
double temp = number;
for (int i = 0; i < digitsAvailable; i++) {
if ((temp /= 10) < 1) {
format += "#";
}
}
return new DecimalFormat(format).format(number);
}
String format = "0.";
for (int i = 0; i < digitsAvailable; i++) {
format += "#";
}
String r = new DecimalFormat(format + "E0").format(number);
int lastLength = r.length() + 1;
while (r.length() > MAX_LENGTH && lastLength > r.length()) {
lastLength = r.length();
r = r.replaceAll("\\.?[0-9]E", "E");
}
return r;
}
This reminded me of a similar question where the OP only had 5 or so spaces for a number and wanted to show a decimal only when there was enough space. But instead of exponents, wanted to use a suffix of (k,m, etc)