I want to make this so that short inputs can still be detected, such as "Londo" and "Lon", but want to keep it small and use it without basically copying and pasting the code, any tips? thank you.
if (Menu.answer1.equals("London"))
{
if (location.equals("London")) {
System.out.print(location + " ");
System.out.print(date + " ");
System.out.print(degrees + "C ");
System.out.print(wind + "MPH ");
System.out.print(winddirection + " ");
System.out.print(weather + " ");
System.out.println("");
}
You can use startsWith()
String city = "London";
if (city.startsWith("Lon")) {
// do something
}
Also if you need to check some substring, you can use contains method:
Menu.answer1 = "London";
Menu.answer1.contains("ondo"); // true
If you want to check against a fixed set of alternatives, you may use a list of valid inputs using contains:
List<String> londonNames = Arrays.asList("London", "Londo", "Lon");
if (londonNames.contains(Menu.answer1)) {
...
}
You can use (case-insensitive) regex to do the same, e.g.:
(?)Lon[a-z]{0,3} where
(?) = case insensitivity
Lon = Initial 3 characters
[a-z]{0,3} = any number of alphabets between 0 and 3
Here's an example:
String regex = "(?)Lon[a-z]{0,3}";
System.out.println("London".matches(regex));
System.out.println("Lond".matches(regex));
System.out.println("Lon".matches(regex));
If the underlying problem is that the user can enter one of several names, and you want to allow abbreviations, then a fairly standard approach is to have a table of acceptable names.
Given the user input, loop through the table testing "does the table entry start with the string typed by the user?" (like one of the previous answers here). If yes, then you have a potential match.
Keep looking. If you get a second match then the user input was ambiguous and should be rejected.
As a bonus, you can collect all names that match, and then use them in an error message. ("Pick one of London, Lonfoo, Lonbar").
This approach has the advantage (compared to a long chain of if-then-else logic) of not requiring you to write more code when all you want to do is have more data.
It automatically allows the shortest unique abbreviation, and will adjust when a once-unique abbreviation is no longer unique because of newly-added names.
Related
I need split String to array. For exapmle i have string str = "apple fruits money Pacific Ocean".
and I try split to array like this:
String []arr = str.split(" ");
But I need the Pacific Ocean to register in one cell of the array. I can't change the separator, because i get data in this form ("apple fruits money Pacific Ocean").
If we admit that multiple consecutive capitalized words need to be considered as a single word, then you can do:
String []arr = str.split("\\s");
then
`String str = "apple fruits money Pacific Ocean";
String[] arr = str.split("\\s");
String[] finalArr = new String[arr.length];
int i = 0;
for (String word : arr) {
// capitalized
if (Character.isUpperCase(word.charAt(0))) {
// check if previous is capitalized
if (Character.isUpperCase(finalArr[i - 1].charAt(0))) {
finalArr[i - 1] = finalArr[i - 1] + word + " ";
} else {
finalArr[i] = word + " ";
}
} else {
finalArr[i] = word;
}
i++;
}
for (String s : finalArr) {
System.out.println(s);
}
}
}`
will result in:
apple
fruits
money
Pacific Ocean
null
You'll need to filter the nulls though and add some checks (if i-1 exists at all).
You need to change the separator as Elliott Frisch stated in his comment. You're not going to be able to determine whether or not a set of words need to stay together if they contain a space. If your word list were separated by another character (such as a comma) then the problem becomes much easier to solve.
String input = "apples,fruits,money,Pacific Ocean";
String[] arr = input.split(",");
Now your array contains each of the words in input.
The problem as described in the question and comments has no solution.
Consider this:
"banana red apple green apple"
This can be split like this:
["banana", "red", "apple", "green", "apple"]
or like this
["banana", "red apple", "green apple"]
Without semantic / contextual analysis it is impossible to know which is more likely to be correct. And it is impossible to know for sure what the (human) user actually meant.
I can't change the separator, because i get data in this form ("apple fruits money Pacific Ocean").
You need to redesign the form or the input syntax so that your software doesn't need to perform this task. There is no other way ... to always get the correct answer.
Think of it this way. Suppose someone gave you a sequence of words in a foreign language on a piece of paper, and asked you to split them correctly. How would you (a human) solve the problem, assuming that you didn't understand the language, and hadn't been given a dictionary or a set of rules? This is equivalent to the task you are setting the computer ...
This way it's not possible. If the string was joined earlier, try using a character other than space. Maybe the pipe | might be an option.
I am a beginner to Java and have written a 260+ line code, menu-driven, procedural-type program. Unfortunately, I must abide by the rules that pertain to Academic Conduct of my university and I cannot paste what code I have here at this exact moment in time, although I will do my best to explain my conundrum in the hopes that more knowledgeable folk can point me in the right direction. I don't necessarily expect solutions in the form of code. My countless Internet searches have been fruitless and I'm kind of lost and frustrated, even with all my reading materials, countless search query combinations and hours poring over forums, including this one.
Basically, my program is almost finished. It's a reservations system that has a few menus asking for user input. There are a few do-while iterations and conditional statements that allow the user to return back to the main menu once they've entered their inputs, along with some basic error validation.
My main issue is with the final submenu; I enter three values using Scanner (all strings) and I can even print those three values to the console prior to being returned to the main menu. If I enter that same submenu again and enter three different inputs, it overwrites the previous set of inputs. Now, I understand that this is to be expected each time the "nextLine" method is invoked but I must capture each individual set of inputs for a reservations summary at the end of the program.
I've tried to store the values in both single and multidimensional arrays along with for (foreach?) loops but they simply fill up the entire index range with the same three values. I've also tried string concatenation, StringBuilder and ArrayLists but the continuous overwriting of those values makes it near impossible for me to achieve anything meaningful with them. Ideally, I just want to enter the values, preserve them somehow, enter and save more values and then retrieve them all at the very end of the program so I can display them using formatted Strings. The maximum number of entries I can make in the submenu is 10. At the risk of asking a vague question, what method would strike you as being the most suitable here? Once I know what tree I have to bark up, I can simply research my way to an answer. This "100 different ways of reaching the same satisfactory outcome" nature of Java - and dare I say programming languages in general - is rather overwhelming for a beginner like me.
An ArrayList would be suitable for the situation. It allows you to add new items to it dynamically, which is exactly what you are trying to do here, isn't it?
But first, I suggest you encapsulate the "three values" that you kept talking about into a class. From what you said, they represent some information about reservations. I'll call this class Reservation:
class Reservation {
// name these variables properly!
private String someValue1;
private String someValue2;
private String someValue3;
#Override // this returns a formatted string representation of a reservation
public String toString() {
return "someValue1: " + someValue1
+ "\nsomeValue2: " + someValue2
+ "\nsomeValue3: " + someValue3;
}
public Reservation(String someValue1, String someValue2, String someValue3) {
this.someValue1 = someValue1;
this.someValue2 = someValue2;
this.someValue3 = someValue3;
}
}
Now you can create an ArrayList<Reservation>:
// put this outside of any method
static ArrayList<Reservation> reservations = new ArrayList<>();
Whenever the user goes to the submenu, you will do something like this, right?
String someValue1 = scanner.nextLine();
String someValue2 = scanner.nextLine();
String someValue3 = scanner.nextLine();
After those lines, create a Reservation:
Reservation reservation = new Reservation(someValue1, someValue2, someValue3);
And put it into the reservations list:
reservations.add(reservation);
When you want to print all the reservations, you just:
for(Reservation r : reservations) {
System.out.println(r);
System.out.println();
}
Not sure I understand the issue, but it seems like you could add your input values to a List<String[]>
List<String[]> data = new ArrayList<>();
// get your first 3 data, add them to the list
data.add(new String[] {"value 1", "value 2", "value 3"});
// get your first 3 new data, add them to the list
data.add(new String[] {"value 4", "value 5", "value 6"});
Then you can print them out
for(String[] values: data) {
System.out.println(values[0] + " | " + values[1] + " | " + values[2] );
}
Outputs
value 1 | value 2 | value 3
value 4 | value 5 | value 6
I'm sure this is fairly simple, however I've tried googling the question but can't find an answer that fits my problem.
I'm playing around with string manipulation and one of the things I'm trying to do is get the first letter of each word. (And then place them all into a string)
I'm having trouble with registering each 'space' so that my If statement will be triggered. Here's what I have so far.
while (scanText.hasNext()) {
boolean isSpace = false;
if (scanText.hasNext(" ")) {isSpace = true;}
String s = scanText.next();
if (isSpace) {firstLetters += s + " ";}
}
Also, if there is a much better way to do this then please let me know
You can also split the original text by spaces, and collect the words.
String input = " Hello world aaa ";
String[] split = input.trim().split("\\s+"); // all types of whitespace; " +" to pick spaces only
// operate on "split" array containing words now: [Hello, world, aaa]
However using regexps here might be overkill.
Assuming that scanText is a Scanner object, you could use something like stated on the documentation:
Scanner s = new Scanner(input).useDelimiter("\\s+"); //regex for spaces
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
If I have a parent string (let's call it output) that contains a list of variable assignments like so ...
status.availability-state available
status.enabled-state enabled
status.status-reason The pool is available
And I want to extract the values of each variable in that list given the variable names, ie the substring after the space following status.availability-state, status.enabled-state, and status.status-reason, such that I end up with three different variable assignments making each of the following String comparisons true ...
String availability = output.substring(TODO);
String enabled = output.substring(TODO);
String reason = output.substring(TODO);
availability.equals("available");
enabled.equals("enabled");
reason.equals("The pool is available");
What is the simplest way to do this? Should I even use substring for this?
This is a little tricky because you need to assign the value to a specific variable - you can't just have a map of keys to variables in Java.
I would consider doing this with a switch:
for (String line : output.split('\n')) {
String[] frags = line.split(' ', 2); // Split the line in 2 at the space.
switch (frags[0]) { // This is the "key" of the variable.
case "status.availability-state":
availability = frags[1]; // This assigns the "value" to the relevant variable.
break;
case "status.enabled-state":
enabled = frags[1];
break;
// ... etc
}
}
It's not very pretty, but you don't have too many options.
There seem to be two questions here -- how to parse the string, and how to assign to variables by name.
Tackle the string parsing one step at a time:
first write a program to read one line at a time and output each one in the body of a loop. String.split() or StringTokenizer are two options here.
next enhance this by writing a method to handle one line. The same tools are helpful here, to split on spaces.
You should now have a program that can print name: status.availability-state, value: available for each line of input.
Next, you're asking to programatically assign to variables based on the name of the parameter.
There is no legitimate way to look at a variable's name at runtime (OK, Java 8 reflection has ways, but it shouldn't be used without very good reason).
So, the best you can do is to use a switch or if statement:
switch(name) {
case status.availability-state:
availability = value;
break;
... etc.
}
However, whenever you use switch or if you should think about whether there's a better way.
Is there any reason you can't turn these variables into Map entries?
configMap.add(name,value);
Then to read it:
doSomethingWith(configMap.get("status.availability");
That's what maps are for. Use them.
This is a similar situation to the rookie mistake of using variables called person1, person2, person3... instead of using an array. Eventually they ask "How do I go from the number 25 to my variable person25?" -- and the answer is, you can't, but an array or list makes it easy. people[number] or people.get(number)
A valid alternative is to split the string by \n and add to a Map. Example:
String properties = "status.availability-state available\nstatus.enabled-state enabled\nstatus.status-reason The pool is available";
Map<String, String> map = Arrays.stream(properties.split("\n"))
.collect(Collectors.toMap(s -> s.split(" ")[0], s -> s.split(" ", 2)[1]));
System.out.println(map.get("status.status-reason"));
Should output The pool is available
This loop will match and extract the variables, and you can then assign them as you see fit:
Pattern regex = Pattern.compile("status\\.(.*?)-.*? ([a-z]+)");
Matcher matcher = regex.matcher(output);
while (matcher.find()) {
System.out.println(matcher.group(1) + "=" + matcher.group(2));
}
status\\. matches "status."
(.*?) matches any sequence of characters but isn't greedy, and captures them
-.* matches dash, any chars, space
([a-z]+) matches any string of lower-case letters, and captures them
Here's one way to do it:
Map<String, String> properties = getProperties(propertiesString);
availability = properties.get("availability-state");
enabled = properties.get("enabled-state");
reason = properties.get("status-reason");
// ...
public void getProperties(String input) {
Map<String, String> properties = new HashMap<>();
String[] lines = output.split("\n");
for (String line : lines) {
String[] parts = line.split(" ");
int keyStartIndex = parts[0].indexOf(".") + 1;
int spaceIndex = parts[1].indexOf(" ");
string key = parts[0].substring(keyStartIndex, spaceIndex);
properties.put(key, parts[1]);
}
return properties;
}
This seems to be a bit more straight-forward, in terms of the code that's setting these values, as each value is set to exactly the value from the map, rather than iterating over some list of strings and seeing if it contains a particular value and doing different things based on that.
This is designed with the primary use-case being that the string is created at runtime in memory. If the properties are created in an external file, this code would still work (after creating the desired String in memory), but it may be a better idea to use either a Properties file, or perhaps a Scanner.
So far I have a code that asks for a user input but a part of my code isn't accepting letters as inputs. For example if i type in say woah123 it'll give me a number format exception. Any way to get around this? Error is at the second line int i = Integer.parseInt(sentence).
Sentence is the user input
sentence.replaceAll("\\D", "");
int i = Integer.parseInt(sentence);
i = i * 2 ;
woah.replaceAll("\\d", "" + i);
System.out.println(woah);
Strings are immutable.
Generally, every modification you made on an immutable object will "give" you another immutable object.
So it should be :
sentence = sentence.replaceAll("\\D", "");
Indeed you have to do the same for woah.
You may read about what is an immutable object.