Input: My name is Bob.
Output: Bob is name My.
I have seen plenty of examples on how to reverse each word and then word sequence in a sentence. However, I do not think I have seen one that I want-example above. This forum was not helpful, because it only focuses on double quote on start and end of a sentence: How to reverse words in a string but keep punctuation in the right place?
What I tried
public void rev2(String str) {
String[] arrStr = str.split(" ");
for (int i = arrStr.length - 1; i >= 0; i--) {
if (!arrStr[i].contains(".")) {
System.out.print(arrStr[i] + " ");
}
}
}
public static void main(String[] args) {
Test t = new Test();
t.rev2("My name is Bob.");
}
The code above does not work as expected. I probably can convert each string to char and use Character.isAlphabet() or may be use pattern?
I could use some ideas. Thanks in advance for your time and help.
Here is a solution that works within the constraints of the question (some of which are assumed):
public void rev2(String str) {
String[] arrStr = str.split(" ");
for (int i = arrStr.length - 1; i >= 0; i--) {
boolean punct = i <= 0 || arrStr[i - 1].contains(".");
if (!arrStr[i].contains(".")) {
System.out.print(arrStr[i]);
} else {
System.out.print(arrStr[i].substring(0, arrStr[i].length() - 1));
}
System.out.print((punct ? ". " : " "));
}
}
public static void main(String[] args) {
Tester t = new Tester();
t.rev2("My name is Bob. I am happy.");
}
Explanation:
The boolean punct looks ahead to see if the next element contains a ".". If so, we are on a sentence boundry and so added a . after the current word. If not, we just put a space. We also add a "." if we are on the last element in the array.
Output:
happy am I. Bob is name My.
If all you want to do regarding punctuation is keep the period at the end of the sentence, you can print the words followed by a space or by the period depending on whether they are the first word or not, and you can remove the period from the last word by calling substring(). Something like this:
public class Test {
public void rev2(String str) {
String[] arrStr = str.split(" ");
for (int i = arrStr.length - 1; i >= 0; i--) {
if (!arrStr[i].contains(".")) {
System.out.print(arrStr[i] + (i == 0 ? "." : " "));
} else {
System.out.print(arrStr[i].substring(0, arrStr[i].length() - 1) + " ");
}
}
}
public static void main(String[] args) {
Test t = new Test();
t.rev2("My name is Bob.");
}
}
Output: Bob is name My.
If you want a less verbose code:
var list = Arrays.asList("My name is Bob".split(" "));
Collections.reverse(list);
list.stream().map(str -> str.concat(" ")).forEach(System.out::print);
Related
I want to create a refactorSeparators method that takes an object of the String type as an argument. Method returns the text from the input object corrected so that if there is any
a comma or a period and there is no space after it, it will insert this space.I'm stuck, don't know what to do next, below is my code. How can I finish it? I wonder how to write this part: if (s.equals(".") && i.next().equals())
public class Separator {
public static void main(String[] args) {
String text = "Periods,hyphens, the last two characters cannot be a period. The rest of them don't. And there you go.";
ArrayList<String> stringArr = new ArrayList<>();
String[] arrOfStr = text.split("");
Iterator i = stringArr.iterator();
for (String s : arrOfStr) {
stringArr.add(s);
System.out.println("{" +s + "}");
}
for (String s : arrOfStr) {
if (s.equals(".") && i.next().equals()) {
String space = " ";
stringArr.add(i.next(, " ");
} else {
System.out.println("error");
}
}
}}
You're over-thinking it:
String refactorSeparators(String str) {
return str.replaceAll("([,.]) ?", "$1 ").trim();
}
The regex ([,.]) ? matches a comma or dot optionally followed by a space, which is replaced with the dot/comma and a space. The trim() removes the space that would be added if there's a dot at the end of the input.
Your main problem is here:
Iterator i = stringArr.iterator();
// ...
for (String s : arrOfStr) {
if (s.equals(".") && i.next().equals()) {
You are iterating both with an iterator and a for-loop, that makes life complicated. I'd suggest using a for-loop over the index.
Also your second equals expression is missing an argument.
Since Bohemian already posted the regex one liner, I might as well post my solution too:
public class PunctuationFixer {
private String text;
private int index;
public static String addMissingWhitespaceAfterPunctuation(String input) {
return new PunctuationFixer(input).fix();
}
private PunctuationFixer(String input) {
this.text = input;
this.index = 0;
}
private String fix() {
while (index < this.text.length() - 1) {
fix(this.text.charAt(index));
index++;
}
return this.text;
}
private void fix(char current) {
if (current == '.' || current == ',') {
addSpaceIfNeeded();
}
}
private void addSpaceIfNeeded() {
if (' ' != (text.charAt(index + 1))) {
text = text.substring(0, index + 1) + " " + text.substring(index + 1);
index++;
}
}
public static void main(String[] args) {
String text = "Periods,hyphens, the last two characters cannot be a period. The rest of them don't. And there you go.";
System.out.println(addMissingWhitespaceAfterPunctuation(text));
}
}
That's an typical parse issue. You have to remember the last char you've read and deppendend on your current char, you know what to do.
public static void main(String[] args) {
String text = "Periods,hyphens, the last two characters cannot be a period.The rest of them don't. And there you go.";
StringBuilder fixedString = new StringBuilder();
String[] arrOfStr = text.split("");
String lastChar = null;
for(String currentChar : arrOfStr) {
if(lastChar != null && (lastChar.equals(",") || lastChar.equals(".")) && !currentChar.equals(" "))
fixedString.append(" ");
fixedString.append(currentChar);
lastChar = currentChar;
}
System.out.println(fixedString);
}
Side note: The shortest and most elegant solution is, of course, #bohemian's. But I suspect it is not in the sense of the homework! ;-)
As I mentioned in the title, i want to create a method in java that find each word from a String and print it out.
That is how it (more less) look like:
public int findFirstLetter(int pos, String text)
{
while (pos<text.length())
{
if (Character.isLetter(text.charAt(pos))==true&&(pos == 0||Character.isLetter(text.charAt(pos-1))==false)){return pos;}
pos++;
}
return -1;
}
public int findLastLetter(int pos, String text)
{
while (pos<text.length()){
if (Character.isLetter(text.charAt(pos))==true&&(pos+2>text.length()||Character.isLetter(text.charAt(pos+1))==false)){return pos;}
pos++;
if (pos == -1){break;};
}
return -1;
}
public void testString (String text)
{
int first = findFirstLetter(0,text);
int last = findLastLetter(0,text);
String word = "";
int startWord = 0;
int i = 0;
while (first!=-1)
{
word = text.substring(first, last+1);
System.out.println("word: "+word);
startWord = text.indexOf(word)+1;
first = findFirstLetter(startWord,text);
if(first == -1){break;}
last = findLastLetter(first,text);
}
When i provide some String as input to this method, the loop is starting to repeat from the middle and doesn't reach the end. For example, in the last phrases the method is repeating "the loop is" over and over again. Could someone give me some advice in order to find what is wrong?
As #Tim Biegeleisen stated in it's comment, you could use split in order to get the words, put them into an array and loop over it in order to print them. Please note that two Options are provided and you should choose 1 of them. If you're learning Java, the second option is more readable and comprehensible.
public void printWords(String s) {
String [] words = s.split("\\s+"); //Option 1: Tim Biegelsman regex
String [] words = s.split(" "); //Option 2: if the words are separated by blanks
for(String word : words) {
System.out.println(word);
}
}
Note also that you could save a line of code in this way:
public void printWords(String s) {
for(String word : s.split(" ")) {
System.out.println(word);
}
}
I am trying to make a program that should checks if the string that the program is currently looking at, contains the word ing in that specific order. I figured out to just split the string with spaces, so each word can be looked at individually. I am stuck on the if condition. The if condition determines if the word has ing in it. For the assignment I can only use one loop and two if statements. I cannot use the string methods tolower or upppercase. Also this what the output needs to look like: (for the output i have a test class that gives me strings to test out)
Words with ing:
Singing Dancing
if I do not find any words what have ing the output should like this
There are no words with ing
Here is my code till now:
public class EndsWith
{
public static void endsWithIng (String s)
{
String[] a = s.splits(" ");
for(int i = 0; i < a.length; i++)
{
// if()
System.out.print(a[i] + "");
}
}
}
I found the answer for my problem. I forgot to mention that the problem also required a specific print statement. My solution is similar but I made a new string and added any words that I found with ing to that new string. Also I used a counter to keep track if a word with ing is even found in the first place. If it is not than I printed after the loop no words with ing found.
public class EndsWith
{// start of cLASS
public static void endsWithIng (String s)
{// START of method
String ing="";
String compare="";
String [] a = s.split(" ");
//System.out.println("Words with ing: ");
int i;
int count=0;
for(i=0;i<a.length;i++)
{//start of for
compare=a[i];
if(compare.matches(".*[iI][nN][gG].*"))
{ //start of if
//System.out.print(compare + " ");
count++;
ing+=a[i] +" ";
}
}
if(count==0)
{
System.out.println("There are no words with ing");
}
else
{
System.out.println("Words with ing: ");
System.out.println(ing);
}
}
}
I think you are looking to split on one (or more) white-space characters. You can also use String.endsWith(String)1. Something like,
public static void endsWithIng(String s) {
String[] a = s.split("\\s+");
for (int i = 0; i < a.length; i++) {
if (a[i].toLowerCase().endsWith("ing")) {
System.out.print(a[i] + " ");
}
}
}
or you could use an enhanced for-each loop like2
public static void endsWithIng(String s) {
String[] a = s.split("\\s+");
for (String value : a) { // <-- for each value in array a
// This checks if the last three characters make the String "ing"
if ("ing".equalsIgnoreCase(value.substring(value.length() - 3))) {
System.out.print(value + " ");
}
}
}
To use a regular expression, beyond String.split(String), you can use String.matches(String) like
public static void endsWithIng(String s) {
String[] a = s.split("\\s+");
for (String value : a) { // <-- for each value in array a
// This test ignores case for iI nN gG
if (value.matches(".*[(i|I)(n|N)(g|G)]$")) {
System.out.println(value);
}
}
}
1You since added the stipulation that you cannot use toLowerCase. Next time, for better help faster, please give all the requirements when you ask the question.
2This example uses Yoda conditions.
i have a list of files in this form:
name_of_file_001.csv
name_of_file_002.csv
name_of_file_123.csv
or
name_of_file.csv
second_name_of_file.csv
i don't know if the file has 001 or not.
how to take name of file (only name_of_file) in java?
Try the following:
int i=0;
while(!fullName.charAt(i).equals('.')&&!fullName.charAt(i).equals('0')){
i++;
}
String name=fullName.substring(0, i);
Take the string from the beginning of the fullName to the first appearance of . or 0.
EDIT:
Referring to the comments and the case of high numbers greater than 1.. and inspired from this answer:
int i=0;
String patternStr = "[0-9\.]";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(fullName);
if(matcher.find()){
i=matcher.start(); //this will give you the first index of the regex
}
String name=fullName.substring(0, i);
EDIT2:
In the case where there's no Extension and the fullname doesn't match the regex(there's no numbers):
if(matcher.find()){
i=matcher.start(); //this will give you the first index of the regex
}else {
i=fullname.length();
}
String name=fullName.substring(0, i);
Or simply we will take all the name.
I modified chsdk's solution with respect to mmxx's comment:
int i=0;
while(i < fullName.length() && ".0123456789".indexOf(fullName.charAt(i)) == -1) {
i++;
}
String name=fullName.substring(0, i);
EDIT:
Added
i < fullName.length()
This little class solves the problem for all the examples shown in main:
public class Example {
private static boolean isNaturalNumber(String str)
{
return str.matches("\\d+(\\.\\d+)?");
}
public static String getFileName(String s) {
String fn = s.split("\\.")[0];
int idx = fn.lastIndexOf('_');
if (idx < 0) {
return fn;
}
String lastPart = fn.substring(idx+1);
System.out.println("last part = " + lastPart);
if (isNaturalNumber(lastPart)) {
return fn.substring(0,idx);
} else {
return fn;
}
}
public static void main(String []args){
System.out.println(getFileName("file_name_001.csv"));
System.out.println(getFileName("file_name_1234.csv"));
System.out.println(getFileName("file_name.csv"));
System.out.println(getFileName("file_name"));
System.out.println(getFileName("file"));
}
}
EDIT 1: Replaced the exception-based check with a regex check.
EDIT 2: Handling file names without any underscores.
i resolved the problem in this mode:
nameOfFile.split("\\.")[0].replaceall("_[0-9]*","");
split("\.")[0] remove ".csv" name_of_file_001.csv => name_of_file_001
.replaceall("_[0-9]*","") "remove, if there is, "_001" name_of_file_001 => name_of_file
the result is the name of file only
So the code I have is for a homework assignment where the user inputs a sentence (string) and I need to search through the string and return the smallest word. However, there must be a number inputted at the first spot in the string. Ex: "4 WHAT IS THIS". Output should be "IS" and ignore the number. The only way I figured out how to ignore the number is to make the loop skip over the first spot where the number would be. It works by itself but whenever I put it into the rest of my program it stops working. Is there anyway to make this program cleaner?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// Lexicographically smallest word
String TheSentence = sc.nextLine();
String[] myWords = TheSentence.split(" ");
int shortestLengths, shortestLocation;
shortestLengths = (myWords[1]).length();
shortestLocation = 1;
for (int i = 1; i < myWords.length; i++) {
if ((myWords[i]).length() < shortestLengths) {
shortestLengths = (myWords[i]).length();
shortestLocation = i;
}
}
System.out.println(myWords[shortestLocation]);
}
Inside your for loop (that should start at i = 0), add code like this:
try {
double value = Double.parseDouble(myWords[i]);
} catch (NumberFormatException e) {
// add the rest of your code here
}
The idea is that you try to transform your word to a number and if you fail, it means it's not a number, so you can use the length logic on the word.
The first thing you should do is to create the function you want to use instead of mixing the relevant code for the exercice with things like reading a line from the input stream.
You can test whether a character is a letter using Character.isLetter(char).
A good exercice is to build a solution using only that function and looking at each character separately (String.charAt(int) method) in a loop.
The solution is to remember where the currently shortest word starts and how long it is.
In practice, I would just use regexes like this:
public static String shortestWord(String sentence) {
String shortest = null;
Pattern word = Pattern.compile("\\w+");
Matcher m = word.matcher(sentence);
while (m.find()) {
String candidate = m.group();
if (shortest == null || shortest.length() > candidate.length())
shortest = candidate;
}
return shortest;
}
You could try using substring, e.g.
String result=inputString.substring(1)
'1' being the second letter in the string, substring returning every value save for the first.
The below basically just shortens up your code..other than that it doesn't change much. That being said..it would be much better to create all this in a method called shortestWord() or something. There is really no reason the code below shouldn't work though.
Revised Code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] myWords = (sc.nextLine()).split(" ");
int shortestLocation = 1
for (int i = 2; i < myWords.length; i++) { // No reason to start at 1 as you have
// already made shortestLocation = 1
if (myWords[i].length() < myWords[shortestLocation].length()) {
shortestLocation = i;
}
}
System.out.println(myWords[shortestLocation]);
}
Suggested Code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] myWords = (sc.nextLine()).split(" ");
System.out.println("The shortest word is: " + shortestWord(myWords));
}
public static String shortestWord(String[] myWords) {
int shortestLocation = 1
for (int i = 2; i < myWords.length; i++) { // No reason to start at 1 as you have
// already made shortestLocation = 1
if (myWords[i].length() < myWords[shortestLocation].length()) {
shortestLocation = i;
}
}
return myWords[shortestLocation];
}