Merge lines that share a word-link - java

so I'm having a small problem in java. I have something like
"Victor Fleming"
"Gone With"
"With The"
"The Wind."
So what the sentence should actually look like is
"Victor Fleming"
"Gone with the wind."
Therefore I'm looking to form a single sentence, by words that are adjacent and the same. If no adjacent same word is detected then the sentence will be separated as in "Victor Fleming" case where Fleming is not the same with Gone, so a new sentence is starting. What I've written so far:
List<String> separatedText = new ArrayList<>();
int i = 0;
while (i < mergedTextByHeightColor.size()) {
if ((i < (mergedTextByHeightColor.size() - 3)) && !(mergedTextByHeightColor.get(i + 1).equals(mergedTextByHeightColor.get(i + 2)))) {
separatedText.add(mergedTextByHeightColor.get(i) + " " + mergedTextByHeightColor.get(i + 1));
i = i + 2;
}
String concatStr = "";
while ((i < (mergedTextByHeightColor.size() - 3)) && (mergedTextByHeightColor.get(i + 1).equals(mergedTextByHeightColor.get(i + 2)))) {
if (concatStr.contains(mergedTextByHeightColor.get(i))) {
concatStr = mergedTextByHeightColor.get(i + 1) + " " + mergedTextByHeightColor.get(i + 3);
} else {
concatStr = mergedTextByHeightColor.get(i) + " " + mergedTextByHeightColor.get(i + 1) + " " + mergedTextByHeightColor.get(i + 3);
}
i = i + 3;
}
separatedText.add(concatStr);
}

We can store the sentences in a String array, then loop through each one.
Inside the loop, we check whether the last word of the last item (by splitting it into an array with .split(" "), then getting the last element) is equal to the first word of the current item. If it is, we first remove the first word of the current item, then append it to a StringBuilder.
If it isn't, then we append the StringBuilder's value to the list, append the current element, and move on.
String[] sentences = {"Victor Fleming", "Gone With", "With The", "The Wind."};
List<String> newsentences = new ArrayList<>();
StringBuilder str = new StringBuilder();
for(int i = 0; i < sentences.length; i++) {
String cur = sentences[i];
if(i != 0) {
String[] a = sentences[i-1].split(" ");
String[] b = cur.split(" ");
String last = a[a.length-1];
String first = b[0];
if(last.equalsIgnoreCase(first)) {
str.append(cur.substring(first.length()));
}else {
newsentences.add(str.toString());
str = new StringBuilder();
str.append(cur);
}
}else {
str.append(cur);
}
}
newsentences.add(str.toString());
System.out.println(Arrays.toString(newsentences.toArray()));
Output:
[Victor Fleming, Gone With The Wind.]

Related

How do I add "and" before the last author's last name?

public String Cite()
{
String authorsList = "";
Collections.sort(authors);
for(Author a: authors)
{
authorsList += a.firstName.toUpperCase().charAt(0) + ". " + a.lastName + ", ";
}
String cite = authorsList + "\"" + title + "\", " + venue + "(" + getAcronym() + ")" + " , " +
publisher;
return cite;
}
How would I go about adding the word "and" to separate the last two names of the list?
Use a for loop with index.
for (int i = 0; i < authors.size(); ++i) {
if (i == authors.size() - 2) {
authorsList += a.firstName.toUpperCase().charAt(0) + ". " + a.lastName + "and ";
} else {
authorsList += a.firstName.toUpperCase().charAt(0) + ". " + a.lastName + ", ";
}
}
public static String Cite(ArrayList<Author> authors){
String authorsList = "";
Collections.sort(authors, new CustomComperator());
int size = authors.size();
int count = 0;
for(Author a: authors) {
if (size ==1) {
authorsList = a.firstName.toUpperCase().charAt(0) + ". " + a.lastName;
}
else if (count == size-2) {
authorsList += a.firstName.toUpperCase().charAt(0) + ". " + a.lastName ;
}
else if (count == size - 1) {
authorsList += " and " + a.firstName.toUpperCase().charAt(0) + ". " + a.lastName ;
}
else{
authorsList += a.firstName.toUpperCase().charAt(0) + ". " + a.lastName + ", ";
}
count ++;
}
return authorsList;
}
You should use a normal for loop, so you can detect that you're on the first and/or last element.
Other changes:
Remove the , after the last author.
Use StringBuilder to build a String.
List<Author> authors = new ArrayList<>(List.of(
new Author("Stephen", "King"),
new Author("John", "Grisham"),
new Author("William", "Shakespeare"),
new Author("Charles", "Dickens") ));
Collections.sort(authors);
StringBuilder buf = new StringBuilder();
for (int i = 0; i < authors.size(); i++) {
Author a = authors.get(i);
if (i != 0)
buf.append(i < authors.size() - 1 ? ", " : " and ");
buf.append(a.firstName.toUpperCase().charAt(0) + ". " + a.lastName);
}
String authorsList = buf.toString();
System.out.println(authorsList);
Output
C. Dickens, J. Grisham, S. King and W. Shakespeare
Oxford comma
Whether or not you want , comma before and (Oxford comma) is of course entirely up to you.
buf.append(i < authors.size() - 1 ? ", " : ", and ");
Output
C. Dickens, J. Grisham, S. King, and W. Shakespeare
UPDATE
Since all 4 other answers at this time gave bad result for a single Author, here is test result for various number of authors.
Full Test
List<Author> allAuthors = List.of(
new Author("Stephen", "King"),
new Author("John", "Grisham"),
new Author("William", "Shakespeare"),
new Author("Charles", "Dickens") );
for (int aCount = 0; aCount <= allAuthors.size(); aCount++) {
List<Author> authors = new ArrayList<>(allAuthors.subList(0, aCount));
Collections.sort(authors);
StringBuilder buf = new StringBuilder();
for (int i = 0; i < authors.size(); i++) {
Author a = authors.get(i);
if (i != 0)
buf.append(i < authors.size() - 1 ? ", " : " and ");
buf.append(a.firstName.toUpperCase().charAt(0) + ". " + a.lastName);
}
String authorsList = buf.toString();
System.out.println(aCount + ": \"" + authorsList + "\"");
}
Output
0: ""
1: "S. King"
2: "J. Grisham and S. King"
3: "J. Grisham, S. King and W. Shakespeare"
4: "C. Dickens, J. Grisham, S. King and W. Shakespeare"
If you want to do the same without loops you could:
Define a toString or similar method inside your Author class:
class Author{
String firstName;
String lastName;
Author(String firstName,String lastName){
this.firstName=firstName;
this.lastName=lastName;
}
#Override
public String toString(){
return String.format("%s. %s",this.firstName.toUpperCase().charAt(0), this.lastName);
}
}
And use the Collectors.joining to create the initial list (comma separated).
List<Author> authors = Arrays.asList(new Author("Jules", "Verne"),
new Author("Pablo", "Neruda"), new Author("JK", "Rowling"));
authors.sort(Comparator.comparing(a -> a.lastName));
StringBuffer result = new StringBuffer(
authors.stream().limit(authors.size() - 1).map(a -> a.toString()).collect(
Collectors.joining(" ,")));
And after that, add the last "and":
if (authors.size() > 1) {
result.append(String.format(" and %s", authors.get(authors.size() - 1).toString()));
} else {
result.append(authors.get(authors.size() - 1).toString());
}
System.out.println(result);
Output: P. Neruda ,J. Rowling and J. Verne

Assert 2 strings are in alpha order

I am currently writing . a test to compare leaderboards entries in a betting table, Firstly i have to compare the result picks or the player (which is working) and then i have to compare each players points (which is working) but if both of these attributes are the same i have to assert the player higher on the table is higher alphabetically. I have created the variables username_player and previous_user to do this but cant figure out how to do it, Im trying to put it in the else if section (which i think is correct). There doesn't seem to be an assert option to do this?
public void test_player_leaderboard_entry() {
int size = playerRows.size();
Integer previous_total = 0;
Integer previous_points = 0;
String previous_user = null;
for (int i = 0; i < size; i++) {
//Position
String position_first_player = Drivers.getDriver().findElement(By.cssSelector("[data-qa-position-value='" + i + "']")).getText();
//Points
String points_player = Drivers.getDriver().findElement(By.cssSelector("[data-qa-points-value='" + i + "']")).getText();
//Username
String username_player = Drivers.getDriver().findElement(By.cssSelector("[data-qa-player-value='" + i + "']")).getText();
//Row Number
Integer row = i + 1;
Integer point_player = Integer.parseInt(points_player);
Integer total_of_won_and_looking_good = 0;
//PICKS
for (int pick_number = 1; pick_number < 5; pick_number++) {
String pick_status = Drivers.getDriver().findElement(By.xpath("//*[#id='root']/div/main/section[2]/section/div/ol/a[" + row + "]/li/div[3]/div[" + pick_number + "]/div")).getAttribute("data-qa-pick-state");
//System.out.println(pick_status);
if (Integer.parseInt(pick_status) == 2 || Integer.parseInt(pick_status) == 1) {
total_of_won_and_looking_good = total_of_won_and_looking_good + 1;
}
} if(previous_total.equals(total_of_won_and_looking_good)) {
Assert.assertTrue(previous_points > point_player);
System.out.println("Picks are the same, points are higher ");
} else if (previous_total.equals(total_of_won_and_looking_good)&& previous_points.equals(point_player)) {
Assert.assertTrue(previous_user.compareTo(username_player) < 0);
}
previous_total = total_of_won_and_looking_good;
previous_points = point_player;
previous_user = username_player;
System.out.println("On row number " + row + " we find " + username_player + " in position " + position_first_player + " with " + total_of_won_and_looking_good + " correct picks and " + points_player + " points!");
}
}
}
You can use the compareTo method.
Try using an assertion for previous_user.compareTo(username_player) <0
You can use compareTo method on Strings which compares them lexicographically. So you can do something like
Assert.assertTrue(previous_user.compareTo(username_player) < 0)
Edit:
Maybe you can try it like this but I am not entirely sure that is what you want:
if(previous_total.equals(total_of_won_and_looking_good)) {
Assert.assertTrue(previous_points > point_player);
System.out.println("Picks are the same, points are higher ");
} else if (previous_points.equals(point_player)) {
Assert.assertTrue(previous_user.compareTo(username_player) < 0);
}

Printing a random string from an array

public static void main(String[] args) {
String word;
String[] RobinWords = {"Hole In A Donut", "Bankruptcy", "Popcorn", "Ravioli", "Hijack", "Camouflage", "Key Hole", "New Year's Eve", "Trampoline", "Zorro", "Hallucination", "Alter Ego", "Backfire", "Batman"};
Random rand = new Random();
word = RobinWords [rand.nextInt(RobinWords.length)];
System.out.println("Holy " + word + ", Batman!");
System.out.println("Holy " + word + ", Batman!");
System.out.println("Holy " + word + ", Batman!");
System.out.println("Holy " + word + ", Batman!");
System.out.println("Holy " + word + ", Batman!");
}
It might seem a little silly but I couldn't figure out how to make the output to be different from one another.
What you likely meant to do
for (int i = 0 ; i < 5 ; i++)
{
word = RobinWords[rand.nextInt()];
System.out.println("Holy " + word + ", Batman");
}
This code will select a randomized index, send it to your array, store that Index's corresponding element in a String then print the string.
Put it in a loop, and get a new random word on each iteration.
String[] robinWords = { "Hole In A Donut", "Bankruptcy", "Popcorn", "Ravioli", //
"Hijack", "Camouflage", "Key Hole", "New Year's Eve", "Trampoline", //
"Zorro", "Hallucination", "Alter Ego", "Backfire", "Batman" };
Random rand = new Random();
for (int i = 0; i < 5; i++) {
int index = rand.nextInt(robinWords.length);
System.out.printf("Holy %s, Batman!%n", robinWords[index]);
}
Note that I have tried to improve the readability of your code by using a more standard name for robinWords and using printf instead of String concatenation. If you need five unique phrases, then you should probably prefer a Set; and assuming you're using Java 8+, you could do something like
Set<String> wordSet = new LinkedHashSet<>();
Random rand = new Random();
while (wordSet.size() < 5) {
int index = rand.nextInt(robinWords.length);
wordSet.add(robinWords[index]);
}
wordSet.stream().forEachOrdered(word ->
System.out.printf("Holy %s, Batman!%n", word));
Try this
System.out.println("Holy " + RobinWords [rand.nextInt(RobinWords.length)] + ", Batman!");
Because when rand.nextInt() execute it only generate random number once

Stuck. Index out of bounds. Can't figure out why

I am trying to write a program that asks the user for a letter (R,G,B) and then after five output the result. There cannot be 2 letters in a row. I get indexoutofbounds when I enter the third letter and the double letter check does not work.
package absolutejava;
import java.util.Scanner;
import java.util.*;
public class RGB {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
int count = 0;
boolean isColor = false;
String finalString = "";
int i = 0;
int j = 1;
String temp = "";
for (count = 0; count < 5;) {
System.out.println("Enter a color. Use R for red, G for green, and B for blue.");
temp = kb.nextLine();
if ((temp.equals("R") || temp.equals("G") || temp.equals("B"))) {
isColor = true;
temp += temp;
} else {
isColor = false;
System.out.println("Invald Color, please choose again");
}
if (isColor == true && j < 6 && i < 5) {
count++;
if (temp.length() > 2 && temp.length() <= 5 && finalString.substring(i, j).equals(temp.substring(i - 1, j - 1))) {
System.out.println("Two colors cannot be next to each other ");
isColor = false;
count--;
} else if (temp.length() == 5) {
finalString = finalString + temp.substring(i);
//debugging line
System.out.println("i " + i + "j " + j + "count " + count + " " + finalString + " length " + temp.length());
i++;
j++;
} else {
finalString = finalString + temp.substring(i, j);
//debugging line
System.out.println("i " + i + "j " + j + "count " + count + " " + finalString + " length " + temp.length());
i++;
j++;
}
}
}
System.out.println(finalString);
}
}
The following line is definitely wrong:
temp += temp;
You're replacing temp with the current input every iteration, so this will have no effect. Even if that wasn't the case, you'd just be adding the same string to itself - e.g. "A" would become "AA."
I assume you meant
finalString += temp;
or something to that effect.
In general, it seems like you're mixing up temp and final in a few places.
One more thing: don't explicitly compare to true and false, it's unnecessary and is generally considered poor style.

Updated output is concatenating with old output

Can anyone figure out why after removing a found value, the output includes all the information from before the remove?
// Prints current items in both arrays
String titles = "";
String lengths = "";
for (int i = 0; i < numOfSongs; i++) {
titles += songTitles[i] + " ";
lengths += songLengths[i] + " ";
}
JOptionPane.showMessageDialog(null, "**Current Playlist**" + "\nSong titles: " + titles + "\nSong lengths: " + lengths);
// Determines if the user wants to remove a song from the current list
boolean found = false;
// If search matches a song in array, set title to null and length to 0
for (int i = 0; i < songTitles.length; i++) {
if (search.equalsIgnoreCase(songTitles[i])) {
found = true;
songTitles[i] = null;
songLengths[i] = 0;
}
}
// Update arrays, song count, and duration across all songs
if (found) {
titles += songTitles[numOfSongs] + " ";
lengths += songLengths[numOfSongs] + " ";
totalDuration -= songLengths[numOfSongs];
numOfSongs--;
}
// Print updated playlist
JOptionPane.showMessageDialog(null, "**Current Playlist**" + "\nSong titles: " + titles + "\nSong lengths: " + lengths);
titles and totalDuration strings are initialized with all the elements in songTitles and songLengths.
If you find search in songTitles you remove it from songTitles but you don't update songTitles. Instead you append on more song title from songTitles.
You probably want to clear songTitles and songLengths and recreate them skipping null values in songTitles. E.g.
titles = "";
lengths = "";
for (int i = 0; i < numOfSongs; i++) {
if (songTitles[i] != null) {
titles += songTitles[i] + " ";
lengths += songLengths[i] + " ";
}
}
Also consider creating your strings like this (Java 8)
String titles = String.join(" ", songTitles);
String lengths = String.join(" ", songLengths);
Below statements are causing to concatenate with old values.
titles += songTitles[numOfSongs] + " ";
lengths += songLengths[numOfSongs] + " ";
You should first clear the existing values by setting strings empty before adding a new value.
titles = "";
lengths = "";

Categories

Resources