Android check if string contains number before a word - java

I am currently using an arraylist to store some text and then later checking that list to see if it contains certain words and parsing them for the numbers. For example my arraylist could contain:
[cancel, port, 4.5, 3 min, 3/4 terminal]
And I want to parse the 3 min to get the number 3. I currently use:
for (int i = 0; i < textArray.size(); i++) {
if (textList.contains("min")
number = Double.parseDouble(textList.get(i).replaceAll("[^0-9]", ""));
}
But the issue I am having is that it will see the 3 min and it will also see the 3/4 terminal because it contains min. Is there a way to use contains to make sure the word is exactly min?

Instead of contains() use endsWith():
if (textList.endsWith(" min") {
number = Double.parseDouble(textList.get(i).replaceAll("[^0-9]", ""));
}

How about checking if the string starts with a number and then checking if that string has an exact match for the word min?
String[] strValues = {
"cancel",
"port",
"4.5",
"3 min",
"3/4 terminal"
};
for(String str : strValues){
if(str.matches("^[0-9].*$"))
System.out.println(str + " starts with a number");
String[] results = str.split("\\s+");
Boolean matchFound = Arrays.asList(results).contains("min");
System.out.println(str + " is a number that contains a the word min");
else
System.out.println(str + " does not start with a number");
}
Code is untested but it should give you what you asked for which was to use contains.
There are better ways though as others have answered

Related

Check String is in a range of numbers Java

Trying to design a simple lottery program. Everything works except checking if the numbers entered are between 1 to 59.
Exercise says the numbers must be stored in a String variable.
so
if(num<0 || num>59) //wont work for me
Tried making another variable
int numConverted = Integer.parseInt(num)
We haven't covered converting String to int in class though so I don't think this is what expected. Got confused trying that way anyway so probably this is wrong.
Here is the code I have currently.
{
Scanner scan = new Scanner(System.in);
String num=""; //num variable is empty untill user inputs numbers
for(int i =0; i<6; i++)
{
System.out.println("Enter your number between 1-59");
num = num +" "+ scan.nextLine();
}
System.out.println("Ticket printed £2. Your numbers are " + num);
}
In your posted code it's obvious that you want the User to supply 6 specific numerical values. These values are appended to the String variable named num (space delimited). You need to obviously do a few things here:
1) Make sure the value supplied by the user is indeed a numerical value;
2) Make sure the numerical values supplied fall within the minimum and maximum scope of the lottery itself (which you have stated is: 1 to 59);
3) Make sure the number entered by the User hasn't been supplied already.
You've been tasked to store the entered values into a String data type variable and that is all fine but at some point you want to carry out value comparisons to make sure that all the entered values actually play within the limits of the lottery.
When the User completes his/her entries, you end up with a space delimited string held in the num string variable. You now need to make sure that these values entered are indeed....numbers from 1 to 59 and none contain alpha characters.
In my opinion (and this is only because you need to store entered values into a String variable), it's best to use your String variable to gather User input, then test the input to make sure it is indeed a string representation of an actual integer number. Once this is established then we test to make sure if falls within the value min/max limits (1-59). Now we need to test to make sure the number entered hasn't already been entered before for this ticket.
Of course with each test described above, if one fails then the User should be prompted to re-enter a proper value. You can do this by utilizing a while loop. Plenty examples of this in StackOverflow but here's a quick example:
Scanner scan = new Scanner(System.in);
String ticketNumbers = "";
for(int i = 0; i < 6; i++) {
Boolean isOK = false;
while (!isOK) {
System.out.println("\nPlease enter your desired 6 ticket numbers:\n"
+ "(from 1 to 59 only)");
String num = scan.nextLine();
//Is the string entered an actual integer number?
//We use the String.matches() method for this with
//a regular expression.
if(!num.matches("\\d+")) {
System.out.println("You must supply a numerical value! "
+ "Try Again...");
continue;
}
if (ticketNumbers.contains(num + " ")) {
System.out.println("The number you supplied has already been chosen!"
+ " Try Again...");
continue;
}
if (Integer.parseInt(num) >= 1 && Integer.parseInt(num) <= 59) {
ticketNumbers+= num + " ";
isOK = true;
}
else {
System.out.println("The number you supply must be from "
+ "1 to 59! Try Again...");
}
}
}
System.out.println("Ticket printed £2. Your numbers are " + ticketNumbers);
How about -
if(Integer.parseInt(num) < 0 || Integer.parseInt(num) > 59)
This should work, place it after the input.
If it works, please mark this as correct, I need the rep!!!
Easy way would be add available numbers (suppose it wont grow more than 60. You can use a loop to add to this as well)
String numbers[] = {"1","2","3", "..."};
Then inside the loop
Arrays.asList(numbers).contains(num);
You can remove prefixing zero in order avoid conflicts with values like '02'
Here everything is String related.
If you don't want to explicitly convert to int, you could use a regular expression.
if (num.matches("[1-5]?[0-9]")) {
...
This checks whether the String consists of (1) maybe a digit from 1 to 5, followed by (2) definitely a digit from 0 to 9. That'll match any number in the range 0-59.
If you've got a whole series of numbers separated by spaces, you could expand this to cover a whole series like this.
if (num.matches("([1-5]?[0-9]\\s+)*[1-5]?[0-9]")) {
This matches any number of repetitions (including zero) of "a number followed by spaces", followed by a single repetition without a space. The "\\s" means "any whitespace character", the "+" after it means "one or more of what precedes", and the "*" means "zero more of what precedes" - which in this case is the term in parentheses.
Oh I see what you are trying to do
This is what you want
Scanner scan = new Scanner(System.in);
String allNums = "";
for(int i =0; i<6; i++)
{
System.out.println("Enter your number between 1-59");
int num = scan.nextInt();//Take the number in as an int
if(num >0 && num < 59)//Check if it is in range
{
allNums += num + " ";//if it is add it to a string
}
else
{
System.out.println("Number not in range");
i--;//go back one iteration if its not in range
}
}
System.out.println("Ticket printed £2. Your numbers are " + allNums);

useDelimiter for any number of whitespace characters in combination with other delimiters?

I'm trying to make a program to just derive a user-entered polynomial. I'm trying to account for things like "3x2 + 5x4 + 3" instead of just "3x2+5x4+3". I currently have the delimiter setup as scan.useDelimiter("[A-Za-z\\s+-]");. I thought this would cover any letter, the + or - symbols, as well as ANY number of whitespace characters? But when I put the input as something like "3x2 + 5x4 + 3" the scanner just stops at that point when I'm using scan.nextInt().
I'll throw in the relevant parts of the code that I'm using to test stuff out. I'm sure there's much more efficient routes(maybe a HashMap, and removing the constant from the list, etc) but I'll worry about that after I get something like this figured out!
ArrayList<Integer> coeffArr = new ArrayList<>();
ArrayList<Integer> expArr = new ArrayList<>();
String polynomial;
Scanner scan = new Scanner(System.in);
System.out.println("Write your polynomial in the form of (coefficient)(variable)(exponent). (ie: 3x2 is 3x squared):");
polynomial = scan.nextLine();
scan = new Scanner(polynomial);
scan.useDelimiter("[A-Za-z\\s+-]");
while(scan.hasNextInt())
{
coeffArr.add(scan.nextInt());
if(scan.hasNextInt())
expArr.add(scan.nextInt());
}
if(coeffArr.size() != expArr.size())
constant = coeffArr.get(coeffArr.size()-1);
for(int i = 0; i < expArr.size(); i++)
{
System.out.print( (coeffArr.get(i) * expArr.get(i)) + "x" + (expArr.get(i)-1) + " ");
}
So essentially, if I put the input as "3x3+5x2+4" it will output "9x2 + 10x1", but if I were to do "3x3 + 5x2 + 4" all I'll get in the output is "9x2". How do I fix that and why does it happen?

Store user input in Arraylist<String> until new line

The problem requires to input different values for each attribute.Ex:
Color Black White
Water Cool Hot Medium
Wind Strong Weak
I made ArrayList of ArrayList of String to store such thing as no. of values of each attribute is not fixed.The user inputs Black White and on hitting new line the program has to start taking values of NEXT attribute( Cool Hot Medium).The no. of attributes has been already specified.I followed some (almost related) answers here and wrote the following code:
ArrayList<ArrayList<String>> attributes = new ArrayList<ArrayList<String>>();
String input;
for(i=0; i<num_of_Attributes ;i++)
{ System.out.print(" Enter attribute no." + i+1 + " : ");
ArrayList<String> list = new ArrayList<String>();
while(! input.equals("\n"))
{
list.add(input);
input = sc.nextLine();
}
attributes.add(list);
}
The program prints "Enter Attribute 1 : " but even after new line it doesn't print "Enter attribute 2 : ".It goes into infinite loop. How can I achieve what the program requires to do? sc is my Scanner object.
You should read:
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextLine%28%29
specifically the part that states:
This method returns the rest of the current line, excluding any line separator at the end
So, if the user inputs an empty line with only the line separator \n, you will read an empty line without such line separator.
Check while (!input.isEmpty()) or, even better, while (!input.trim().isEmpty())
As a more general rule, you can debug your program (or even just print input) to try to find out yourself what is the actual value you are checking.
As a quick-Hack you can do sth. like
for (i = 0; i < num_of_Attributes; i++) {
input = " ";
System.out.print(" Enter attribute no." + (i + 1) + " : ");
ArrayList<String> list = new ArrayList<String>();
while (!input.isEmpty()) {
list.add(input);
input = sc.readLine();
}
attributes.add(list);
}
not nice but it works. Please also watch out for calculating in String concaternation. In you code it will print 01, 11, 21 and so on. With brackets it will work.

Using Files.lines with .map(line -> line.split("multiple delimiters"))

I have an input file with the following format:
Ontario:Brampton:43° 41' N:79° 45' W
Ontario:Toronto:43° 39' N:79° 23' W
Quebec:Montreal:45° 30' N:73° 31' W
...
I have a class named where the values will go.
example:
Province: Ontario
City: Brampton
LatDegrees: 43
LatMinutes: 41
LatDirection: N
LongDegrees: 79 .... etc
I have already completed a method that parses this out correctly, but i'm trying to learn if this can be done better with Java 8 using Streams, Lambdas.
If I start with the following:
Files.lines(Paths.get(inputFile))
.map(line -> line.split("\\b+")) //this delimits everything
//.filter(x -> x.startsWith(":"))
.flatMap(Arrays::stream)
.forEach(System.out::println);
Can someone please help me reproduce the following please ?
private void parseLine(String data) {
int counter1 = 1; //1-2 province or city
int counter2 = 1; //1-2 LatitudeDirection,LongitudeDirection
int counter3 = 1; //1-4 LatitudeDegrees,LatitudeMinutes,LongitudeDegrees,LongitudeMinutes
City city = new City(); //create City object
//String read = Arrays.toString(data); //convert array element to String
String[] splited = data.split(":"); //set delimiter
for (String part : splited) {
//System.out.println(part);
char firstChar = part.charAt(0);
if(Character.isDigit(firstChar)){ //if the first char is a digit, then this part needs to be split again
String[] splited2 = part.split(" "); //split second time with space delimiter
for (String part2: splited2){
firstChar = part2.charAt(0);
if (Character.isDigit(firstChar)){ //if the first char is a digit, then needs trimming
String parseDigits = part2.substring(0, part2.length()-1); //trim trailing degrees or radians character
switch(counter2++){
case 1:
city.setLatitudeDegrees(Integer.parseInt(parseDigits));
//System.out.println("LatitudeDegrees: " + city.getLatitudeDegrees());
break;
case 2:
city.setLatitudeMinutes(Integer.parseInt(parseDigits));
//System.out.println("LatitudeMinutes: " + city.getLatitudeMinutes());
break;
case 3:
city.setLongitudeDegrees(Integer.parseInt(parseDigits));
//System.out.println("LongitudeDegrees: " + city.getLongitudeDegrees());
break;
case 4:
city.setLongitudeMinutes(Integer.parseInt(parseDigits));
//System.out.println("LongitudeMinutes: " + city.getLongitudeMinutes());
counter2 = 1; //reset counter2
break;
}
}else{
if(counter3 == 1){
city.setLatitudeDirection(part2.charAt(0));
//System.out.println("LatitudeDirection: " + city.getLatitudeDirection());
counter3++; //increment counter3 to use longitude next
}else{
city.setLongitudeDirection(part2.charAt(0));
//System.out.println("LongitudeDirection: " + city.getLongitudeDirection());
counter3 = 1; //reset counter 3
//System.out.println("Number of cities: " + cities.size());
cities.add(city);
}
}
}
}else{
if(counter1 == 1){
city.setProvince(part);
//System.out.println("\nProvince: " + city.getProvince());
counter1++;
}else if(counter1 == 2){
city.setCity(part);
//System.out.println("City: " + city.getCity());
counter1 = 1; //reset counter1
}
}
}
}
There's probably a better solution to my parseLine() method no doubt, but I would really like to condense that as outlined above.
Thanks !!
Let’s start with some general notes.
Your sequence .map(line -> line.split("\\b+")).flatMap(Arrays::stream) isn’t recommended. These two steps will first create an array before creating another stream wrapping that array. You can skip the array step by using splitAsStream though this requires you to deal with Pattern explicitly instead of hiding it within String.split:
.flatMap(Pattern.compile("\\b+")::splitAsStream)
but note that in this case, splitting into words doesn’t really pay off.
If you want to keep your original parseLine method, you can simply do
Files.lines(Paths.get(inputFile))
.forEach(this::parseLine);
and you’re done.
But seriously, that is not a real solution. To do pattern matching, you should use a library designated to pattern matching, e.g. the regex package. You are using it already, when you do splitting via split("\\b+") but that’s far behind from what it can do for you.
Lets define the pattern:
(…) forms a group that allows capturing the matching part so we can extract it for our result
[^:]* specifies a token consisting of arbitrary characters except the colon ([^:]) of arbitrary length (*)
\d+ defines a number (d = numeric digit, + = one or more)
[NS] and [WE] match a single character being either N or S, or either W or E, respectively
so the entire pattern you are looking for is
([^:]*):([^:]*):(\d+)° (\d+)' ([NS]):(\d+)° (\d+)' ([WE])
and the entire parse routine will be:
static Pattern CITY_PATTERN=Pattern.compile(
"([^:]*):([^:]*):(\\d+)° (\\d+)' ([NS]):(\\d+)° (\\d+)' ([WE])");
static City parseCity(String line) {
Matcher matcher = CITY_PATTERN.matcher(line);
if(!matcher.matches())
throw new IllegalArgumentException(line+" doesn't match "+CITY_PATTERN);
City city=new City();
city.setProvince(matcher.group(1));
city.setCity(matcher.group(2));
city.setLatitudeDegrees(Integer.parseInt(matcher.group(3)));
city.setLatitudeMinutes(Integer.parseInt(matcher.group(4)));
city.setLatitudeDirection(line.charAt(matcher.start(5)));
city.setLongitudeDegrees(Integer.parseInt(matcher.group(6)));
city.setLongitudeMinutes(Integer.parseInt(matcher.group(7)));
city.setLongitudeDirection(line.charAt(matcher.start(8)));
return city;
}
and I really hope you are calling your hard-to-read method never “condense” anymore…
Using the routine above, a clean Stream-based processing solution would look like
List<City> cities = Files.lines(Paths.get(inputFile))
.map(ContainingClass::parseCity).collect(Collectors.toList());
to collect a file into a new list of cities.

Java SE array help needed please

I need some help here with my java school work.
We were told to prompt the user for five words and from there determine the longest word of them and print to console the longest word as well as the number of characters in it.
Right now, I only manage to sort them out using the arrays by displaying the longest number of characters but i'm not sure how to display the word itself. Can someone please help me with it and please bear in mind i'm a total newbie in programming and my progress is still just in the basics so try to make it not too complicated for me please. In addition, feel free to pinpoint those redundant codes as I know I have quite a few. :) Thanks!
import java.util.Scanner;
import java.util.Arrays;
class LongestWord
{
public static void main(String [] args)
{
Scanner theInput = new Scanner(System.in);
System.out.println("Please enter your five words");
String fWord = theInput.next();
String sWord = theInput.next();
String tWord = theInput.next();
String fhWord = theInput.next();
String ffWord = theInput.next();
System.out.println(fWord + sWord + tWord + fhWord + ffWord);
int [] wordCount = new int[5];
wordCount[0] = fWord.length();
wordCount[1] = sWord.length();
wordCount[2] = tWord.length();
wordCount[3] = fhWord.length();
wordCount[4] = ffWord.length();
Arrays.sort(wordCount);
System.out.println(wordCount[4]);
}
}
You need to add all the string to array and iterate all of them.
sample:
String [] wordCount = new String[5];
wordCount[0] = fWord;
wordCount[1] = sWord;
wordCount[2] = tWord;
wordCount[3] = fhWord;
wordCount[4] = ffWord;
String longest = "";
longest = wordCount[0]; //get the first array of words for checking
for(String s : wordCount) //iterate to all the array of words
{
if(longest.length() < s.length()) //check if the last longest word is greater than the current workd
longest = s; //if the current word is longer then make it the longest word
}
System.out.println("Longest Word: " + longest + " lenght: " + longest.length());
result:
Please enter your five words
12345
1234
123
12
1
123451234123121
Longest Word: 12345 lenght: 5
You need to store all words into array and get the maximum value after sort according to its length.
String[] words = ....//Store all words into this array.
Arrays.sort(words, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o2.length() - o1.length();
}
});
System.out.println(words[0]);
or, if you use java-8 than you will get the result more easily,
String longWord=
Arrays.stream(words).max((o1, o2)->o1.length()-o2.length()).get();
Instead of putting lengths into an array, you should put all the words in an array and then loop them using for/while and check length of each string comparing with the previous one to record the max length string.
Or another way may be to read strings using loop and you can perform same logic of comparing lengths without using additional array.

Categories

Resources