I have product description, furniture, many words and I need to find the size (dimensions) of the product. The problem is, the format of the description of the size is not always the same. Only one thing stays same : letter "x" between the numbers, and if there is "x" in the text and another "x" just a few chars away, it is for sure the size description.
Possible formats of size description /all of them appears/:
size:110x76x60 cm /without spaces/
size: 150 x 64,5 x 200 cm /with spaces/
Size: l90 x h55 x w60 cm /as length, height, width/
Size: 149 x v110 x h40 /only some numbers have letters before them/
And not to mention, the numbers dont have to be 3 digits, they can be only 2 digits. But if it is easier to do it for only one type of format, I take it :) and I let the program check the whole list for all the possible formats again and again.
What have you tried so far?
Sounds like a perfect job for a regular expression
JavaDocs have a wealth of information on regular expressions and how to implement them in java code here:
https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
I'm not proud of it, but it works and should give you an idea for making it recursive. It will also allow you to NOT learn regex, which not everyone wants to learn:
This code works and will get you the sizes you are looking for:
public class App {
public static void main(String[] args) {
int l;
int h;
int w;
String text = "Size: l90 x h55 x w60";
String text2 = text.replaceAll("\\D+"," ").trim();
System.out.println(text2);
String[] sizes = text2.split(" ");
l = Integer.valueOf(sizes[0]);
h = Integer.valueOf(sizes[1]);
w = Integer.valueOf(sizes[2]);
}
}
You can use a Matcher and a regular expression.
Matcher matcher = Pattern.compile("(\d+(?:,\d+)?) *x *[a-zA-Z]*(\d+(?:,\d+)?) *x *[a-zA-Z]*(\d+(?:,\d+)?)").matcher(productDescription);
while (matcher.find()) {
String number1 = matcher.group(1);
String number2 = matcher.group(2);
String number3 = matcher.group(3);
}
Related
In this code, I'm trying to split a string at a definite position, but it doesn't work and i'm not sure what to put, knowing that I'm trying to have it in the format "xy" without spaces, commas, anything.
import java.util.*;
public class xy {
public static void main(String[] args) {
System.out.println("Enter a number with the format 'xy'. x is the row number and y the column number.");
Scanner scanner = new Scanner(System.in);
String[] xy = scanner.nextLine().split(charAt(1)); // not sure what to put here so I tried charAt but it doesn't work
String x = xy [0];
String y = xy [1];
}
}
In this code, I'm trying to split a string at a definite position, but it doesn't work and i'm not sure what to put, knowing that I'm trying to have it in the format "xy" without spaces, commas, anything
You don't have to use split, there is no delimiter in the input received. Since the expected input is of xy. Receive it as a String and use charAt:
String input = scn.nextLine();
char x = input.charAt(0);
char y = input.charAt(1);
Or
String x = input.substring(0, 1);
String y = input.substring(1);
In this case you don't need to split. You basically know that the first string should go from index 0 to n-1, and then you got a second string from n-1 to "length".
Thus: don't split; simply call substring() twice, and give the required numbers.
And as you only deal with two chards in the first place; just go:
char x = str.charAt(0);
char y = str.charAt(1);
Done.
I'm wondering about how to replace generic characters in a Java string:
String original = "alt width = (SOME NUMBERS)"
and I want to make it like
String edited = "alt width = 640"
I haven't found out anything about on the web.
To be generic enough to replace any integer number:
int number; // this can be any integer
String original = String.format("alt width = %d",number);
Or if the numbers are represented as a String e.g "111,121"
String numbers;
String original = String.format("alt width = %s",numbers);
The replace method should do the trick:
String edited = original.replace("(SOME NUMBERS)", "640");
EDIT:
Based on the clarification in the comments, you could just remove the last three characters and replace them with what you need:
String edited = original.substring(0, original.length() - 3) + "640";
The most obvious answer is String.replace option. but you already got that answer.
A more generic option is using regular expressions:
String original = "alt width = 123";
int someNumbers = 640;
String edited=original.replaceFirst("[0-9]+",Integer.toString(someNumbers));
System.out.println(edited);
This will replace any numbers on the string. So the input string can be different but you'll get the same results:
String original = "alt width = 123 cm";
String original = "alt width = 123; alt height = 456"; //only 123 will be replaced 456 will be left as is.
You can modify the regex to fit other criteria.
The title speaks for itself. I'm trying to create a calculator that integrates polynomial functions using basic coding, not just whipping out a math operator to do it for me :). I haven't had to go far until I hit a wall, as I'm unable to find a way to: create a substring of the numbers in the original string until a non-numerical character is reached. i.e. if the string is 123x, I want to create a substring of 123, without the 'x'. Here is what I've got so far:
public static void indefinite()
{
int x = 0;
System.out.print("Enter your function to integrate:\n F ");
Scanner input = new Scanner(System.in);
String function = input.nextLine();
String s1 = "";
for (int i = 0; i < function.length(); i++)
{
s1 = s1 + function.substring(x, i+1);
x = i+1;
}
}
It all looks a bit nonsensical, but basically, if the string 'function' is 32x^4, I want the substring to be 32. I'll figure out the rest myself, but this part I cant seem to do.
p.s. i know the for loop's repetition variable is wrong, it shouldn't repeat until the end of the string if I'm looking at functions with more than just 2x^3. I haven't gotten around trying to figure that out yet, so I just made sure it does it for 1 part.
Use replaceAll() to "extract" it:
String number = str.replaceAll("\\D.*", "");
This replaces the first non digit and everything after it with nothing (effectively deleting it), leaving you with just the number.
You can also go directly to a numeric primitive, without having to use a String variable if you prefer (like me) to have less code:
int number = Integer.parseInt(str.replaceAll("\\D.*", ""));
You could split your string at the letter-digit marks, like so:
str.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
For instance, "123x54y7z" will return [123, x, 54, y, 7, z]
I want to export pattern of bit stream in a String varilable. Assume our bit stream is something like bitStream="111000001010000100001111". I am looking for a Java code to save this bit stream in a specific array (assume bitArray) in a way that all continous "0"s or "1"s be saved in one array element. In this example output would be somethins like this:
bitArray[0]="111"
bitArray[1]="00000"
bitArray[2]="1"
bitArray[3]="0"
bitArray[4]="1"
bitArray[5]="0000"
bitArray[6]="1"
bitArray[7]="0000"
bitArray[8]="1111"
I want to using bitArray to calculate the number of bit which is stored in each continous stream. For example in this case the final output would be, "3,5,1,1,1,4,1,4,4". I figure it out that probably "split" method would solve this for me. But I dont know what splitting pattern would do that for me, if i Using bitStream.split("1+") it would split on contious "1" pattern, if i using bitStream.split("0+") it will do that base on continous"0" but how it could be based on both?
Mathew suggested this solution and it works:
var wholeString = "111000001010000100001111";
wholeString = wholeString.replace('10', '1,0');
wholeString = wholeString.replace('01', '0,1');
stringSplit = wholeString.split(',');
My question is "Is this solution the most efficient one?"
Try replacing any occurrence of "01" and "10" with "0,1" and "1,0" respectively. Then once you've injected the commas, split the string using the comma as the delimiting character.
String wholeString = "111000001010000100001111"
wholeString = wholeString.replace("10", "1,0");
wholeString = wholeString.replace("01", "0,1");
String stringSplit[] = wholeString.split(",");
You can do this with a simple regular expression. It matches 1s and 0s and will return each in the order they occur in the stream. How you store or manipulate the results is up to you. Here is some example code.
String testString = "111000001010000100001111";
Pattern pattern = Pattern.compile("1+|0+");
Matcher matcher = pattern.matcher(testString);
while (matcher.find())
{
System.out.print(matcher.group().length());
System.out.print(" ");
}
This will result in the following output:
3 5 1 1 1 4 1 4 4
One option for storing the results is to put them in an ArrayList<Integer>
Since the OP wanted most efficient, I did some tests to see how long each answer takes to iterate over a large stream 10000 times and came up with the following results. In each test the times were different but the order of fastest to slowest remained the same. I know tick performance testing has it's issues like not accounting for system load but I just wanted a quick test.
My answer completed in 1145 ms
Alessio's answer completed in 1202 ms
Matthew Lee Keith's answer completed in 2002 ms
Evgeniy Dorofeev's answer completed in 2556 ms
Hope this helps
I won't give you a code, but I'll guide you to a possible solution:
Construct an ArrayList<Integer>, iterate on the array of bits, as long as you have 1's, increment a counter and as soon as you have 0, add the counter to the ArrayList. After this procedure, you'll have an ArrayList that contain numbers, etc: [1,2,2,3,4] - Representing a serieses of 1's and 0's.
This will represent the sequences of 1's and 0's. Then you construct an array of the size of the ArrayList, and fill it accordingly.
The time complexity is O(n) because you need to iterate on the array only once.
This code works for any String and patterns, not only 1s and 0s. Iterate char by char, and if the current char is equal to the previous one, append the last char to the last element of the List, otherwise create a new element in the list.
public List<String> getArray(String input){
List<String> output = new ArrayList<String>();
if(input==null || input.length==0) return output;
int count = 0;
char [] inputA = input.toCharArray();
output.add(inputA[0]+"");
for(int i = 1; i <inputA.length;i++){
if(inputA[i]==inputA[i-1]){
String current = output.get(count)+inputA[i];
output.remove(count);
output.add(current);
}
else{
output.add(inputA[i]+"");
count++;
}
}
return output;
}
try this
String[] a = s.replaceAll("(.)(?!\\1)", "$1,").split(",");
I tried to implement #Maroun Maroun solution.
public static void main(String args[]){
long start = System.currentTimeMillis();
String bitStream ="0111000001010000100001111";
int length = bitStream.length();
char base = bitStream.charAt(0);
ArrayList<Integer> counts = new ArrayList<Integer>();
int count = -1;
char currChar = ' ';
for (int i=0;i<length;i++){
currChar = bitStream.charAt(i);
if (currChar == base){
count++;
}else {
base = currChar;
counts.add(count+1);
count = 0;
}
}
counts.add(count+1);
System.out.println("Time taken :" + (System.currentTimeMillis()-start ) +"ms");
System.out.println(counts.toString());
}
I believe it is more effecient way, as he said it is O(n) , you are iterating only once. Since the goal to get the count only not to store it as array. i woul recommen this. Even if we use Regular Expression ( internal it would have to iterate any way )
Result out put is
Time taken :0ms
[1, 3, 5, 1, 1, 1, 4, 1, 4, 4]
Try this one:
String[] parts = input.split("(?<=1)(?=0)|(?<=0)(?=1)");
See in action here: http://rubular.com/r/qyyfHNAo0T
This may be a simple question, but I have been Googling for over an hour and haven't found an answer yet.
I'm trying to simply use the String.split() method with a small Android application to split an input string. The input string will be something along the lines of: "Launch ip:192.168.1.101;port:5900". I'm doing this in two iterations to ensure that all of the required parameters are there. I'm first trying to do a split on spaces and semicolons to get the individual tokens sorted out. Next, I'm trying to split on colons in order to strip off the identification tags of each piece of information.
So, for example, I would expect the first round of split to give me the following data from the above example string:
(1) Launch
(2) ip:192.168.1.101
(3) port:5900
Then the second round would give me the following:
(1) 192.168.1.101
(2) 5900
However, the following code that I wrote doesn't give me what's expected:
private String[] splitString(String inputString)
{
String[] parsedString;
String[] orderedString = new String[SOSLauncherConstants.SOCKET_INPUT_STRING_PARSE_VALUE];
parsedString = inputString.trim().split("; ");
Log.i("info", "The parsed data is as follows for the initially parsed string of size " + parsedString.length + ": ");
for (int i = 0; i < parsedString.length; ++i)
{
Log.i("info", parsedString[i]);
}
for (int i = 0; i < parsedString.length; ++i )
{
if (parsedString[i].toLowerCase().contains(SOSLauncherConstants.PARSED_LAUNCH_COMMAND_VALUE))
{
orderedString[SOSLauncherConstants.PARSED_COMMAND_WORD] = parsedString[i];
}
if (parsedString[i].toLowerCase().contains("ip"))
{
orderedString[SOSLauncherConstants.PARSED_IP_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("port"))
{
orderedString[SOSLauncherConstants.PARSED_PORT_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("username"))
{
orderedString[SOSLauncherConstants.PARSED_USERNAME_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("password"))
{
orderedString[SOSLauncherConstants.PARSED_PASSWORD_VALUE] = parsedString[i].split(":")[1];
}
else if (parsedString[i].toLowerCase().contains("color"))
{
orderedString[SOSLauncherConstants.PARSED_COLOR_VALUE] = parsedString[i].split(":")[1];
}
}
Log.i("info", "The parsed data is as follows for the second parsed string of size " + orderedString.length + ": ");
for (int i = 0; i < orderedString.length; ++i)
{
Log.i("info", orderedString[i]);
}
return orderedString;
}
For a result, I'm getting the following:
The parsed data is as follows for the parsed string of size 1:
launch ip:192.168.1.106;port:5900
The parsed data is as follows for the second parsed string of size 6:
launch ip:192.168.1.106;port:5900
192.168.1.106;port
And then, of course, it crashes because the for loop runs into a null string.
Side Note:
The following snippet is from the constants class that defines all of the string indexes --
public static final int SOCKET_INPUT_STRING_PARSE_VALUE = 6;
public static final int PARSED_COMMAND_WORD = 0;
public static final String PARSED_LAUNCH_COMMAND_VALUE = "launch";
public static final int PARSED_IP_VALUE = 1;
public static final int PARSED_PORT_VALUE = 2;
public static final int PARSED_USERNAME_VALUE = 3;
public static final int PARSED_PASSWORD_VALUE = 4;
public static final int PARSED_COLOR_VALUE = 5;
I looked into needing a possible escape (by inserting a \\ before the semicolon) on the semicolon delimiter, and even tried using it, but that didn't work. The odd part is that neither the space nor the semicolon function as a delimiter, yet the colon works on the second time around. Does anybody have any ideas what would cause this?
Thanks for your time!
EDIT: I should also add that I'm receiving the string over a WiFi socket connection. I don't think this should make a difference, but I'd like you to have all of the information that you need.
String.split(String) takes a regex. Use "[; ]". eg:
"foo;bar baz".split("[; ]")
will return an array containing "foo", "bar" and "baz".
If you need groups of spaces to work as a single delimiter, you can use something like:
"foo;bar baz".split("(;| +)")
I believe String.split() tries to split on each of the characters you specify together (or on a regex), not each character individually. That is, split(";.") would not split "a;b.c" at all, but would split "a;.b".
You may have better luck with Guava's Splitter, which is meant to be slightly less unpredictable than java.lang.String.split.
I would write something like
Iterable<String> splits = Splitter.on(CharMatcher.anyOf("; ")).split(string);
but Splitter also provides fluent-style customization like "trim results" or "skip over empty strings."
Is there a reason why you are using String.split(), but not using Regular Expressions? This is a perfect candidate for regex'es, esp if the string format is consistent.
I'm not sure if your format is fixed, and if it is, then the following regex should break it down for you (am sure that someone can come up with an even more elegant regex). If you have several command strings that follow, then you can use a more flexible regex and loop over all the groups:
Pattern p = Pattern.compile("([\w]*)[ ;](([\w]*):([^ ;]*))*");
Matcher m = p.match( <input string>);
if( m.find() )
command = m.group(1);
do{
id = m.group(3);
value = m.group(4);
} while( m.find() );
A great place to test out regex'es online is http://www.regexplanet.com/simple/index.html. It allows you to play with the regex without having to compile and launch you app every time if you just want to get the regex correct.