currently I'm trying to make a method that does the following:
Takes 3 String Arrays (words, beforeList, and afterList)
Looks for words that are in both words and in beforeList, and if found, replaces with word in afterList
Returns a new array that turns the elements with characters in afterList into new elements by themselves
For example, here is a test case, notice that "i'm" becomes split into two elements in the final array "i" and "am":
String [] someWords = {"i'm", "cant", "recollect"};
String [] beforeList = {"dont", "cant", "wont", "recollect", "i'm"};
String [] afterList = {"don't", "can't", "won't", "remember", "i am"};
String [] result = Eliza.replacePairs( someWords, beforeList, afterList);
if ( result != null && result[0].equals("i") && result[1].equals("am")
&& result[2].equals("can't") && result[3].equals("remember")) {
System.out.println("testReplacePairs 1 passed.");
} else {
System.out.println("testReplacePairs 1 failed.");
}
My biggest problem is in accounting for this case of whitespaces. I know the code I will post below is wrong, however I've been trying different methods. I think my code right now should return an empty array that is the length of the first but accounted for spaces. I realize it may require a whole different approach. Any advice though would be appreciated, I'm going to continue to try and figure it out but if there is a way to do this simply then I'd love to hear and learn from it! Thank you.
public static String[] replacePairs(String []words, String [] beforeList, String [] afterList) {
if(words == null || beforeList == null || afterList == null){
return null;
}
String[] returnArray;
int countofSpaces = 0;
/* Check if words in words array can be found in beforeList, here I use
a method I created "inList". If a word is found the index of it in
beforeList will be returned, if a word is not found, -1 is returned.
If a word is found, I set the word in words to the afterList value */
for(int i = 0; i < words.length; i++){
int listCheck = inList(words[i], beforeList);
if(listCheck != -1){
words[i] = afterList[listCheck];
}
}
// This is where I check for spaces (or attempt to)
for(int j = 0; j < words.length; j++){
if(words[j].contains(" ")){
countofSpaces++;
}
}
// Here I return an array that is the length of words + the space count)
returnArray = new String[words.length + countofSpaces];
return returnArray;
}
Here's one of the many ways of doing it, assuming you have to handle cases where words contain more than 1 consecutive spaces:
for(int i = 0; i < words.length; i++){
int listCheck = inList(words[i], beforeList);
if(listCheck != -1){
words[i] = afterList[listCheck];
}
}
ArrayList<String> newWords = new ArrayList<String>();
for(int i = 0 ; i < words.length ; i++) {
String str = words[i];
if(str.contains(' ')){
while(str.contains(" ")) {
str = str.replace(" ", " ");
}
String[] subWord = str.split(" ");
newWords.addAll(Arrays.asList(subWord));
} else {
newWords.add(str);
}
}
return (String[])newWords.toArray();
Related
Need help simplifying split() implementation. Unfortunately split() is not covered as part of AP JAVA. I need to present to high school students and need a simple easy to understand approach. Here's what I've come up with so far but was wondering if I am missing something obvious.
String[] tokens = new String[3];
boolean exit = false;
do{
System.out.print( "Please enter first name, last name and password to logon or
create a new account \n" + "use a space to seperate entries,
no commas : ");
input = kboard.nextLine();
int spaces = 0;
if(input.length() == 0) exit = true;
if(!exit){
//tokens = input.split(" ");
int idx;
int j = 0;
for (int i = 0; i < input.length();){
idx = input.indexOf(" ",i);
if(idx == -1 || j == 3) {
i = input.length();
tokens[j] = input.substring(i);
}else{
tokens[j] = input.substring(i,idx);
i = idx + 1;
}
j++;
}
spaces = j - 1 ;
}
// check we have 2 and no blank line
}while (spaces != 2 && exit == false);
I made a new Split implementation from scratch, that at least in my opinion (subjective) is "simpler" to comprehend. You may or may not find it useful.
public static String[] split(String input, char separator) {
// Count separator (spaces) to determine array size.
int arrSize = (int)input.chars().filter(c -> c == separator).count() + 1;
String[] sArr = new String[arrSize];
int i = 0;
StringBuilder sb = new StringBuilder();
for (char c : input.toCharArray()) { // Checks each char in string.
if (c == separator) { // If c is sep, increase index.
sArr[i] = sb.toString();
sb.setLength(0); // Clears the buffer for the next word.
i++;
}
else { // Else append char to current word.
sb.append(c);
}
}
sArr[i] = sb.toString(); // Add the last word (not covered in the loop).
return sArr;
}
I assumed you wanted to use primitive arrays for teaching, otherwise, I would have returned an ArrayList to further simplify. If StringBuilder is too complicated for your students, you can replace it with normal string-concatenation (less efficient and bad practice).
I've tried to create a method that takes in an array of strings and returns a single formatted string.
The last word should be separated by the word 'and' instead of a comma.
But it doesn't work as expected :)
It doesn't replace the last comma by the word "and".
Can you please advise where is my mistake.
thanks.
public class Kata {
public static String formatWords(String[] words) {
List<String> words1 = Arrays.asList(words);
ListIterator<String> wordIter = words1.listIterator();
StringBuilder out = new StringBuilder();
while (wordIter.hasNext()) {
out.append(wordIter.next());
if (wordIter.hasNext()) {
out.append(",");
}
}
return out.toString().replaceAll(",$", "and");
}
}
Since you may have empty items, first use a list to clear the empty items:
public static String formatWords(String[] words) {
if (words == null)
return "";
List<String> list = new ArrayList<>();
for (String word : words) {
word = word.trim();
if (!word.isEmpty())
list.add(word);
}
StringBuilder out = new StringBuilder();
int len = list.size();
for (int i = 0; i < len; i++) {
out.append(list.get(i));
if (i == len - 2)
out.append(" and ");
else if (i < len - 2)
out.append(",");
}
return out.toString();
}
public static void main(String[] args) {
String[] array = {"", "apples", "", "oranges", "", "melons", ""};
System.out.println(formatWords(array));
}
will print:
apples,oranges and melons
I'd iterate up to the before-last element and concat the strings with commas, and then concat the last one with an "and":
public static String formatWords(String[] words) {
// Handle nulls and empty arrays
if (words == null || words.length) {
return "";
}
// Handle the first word
StringBuilder sb = new StringBuilder(words[0]);
// Handle all the words from the second to the before last
for (int i = 1; i < words.lengh - 1; ++i) {
sb.append(", ").append(word[i]);
}
// Check that there are at least two words
if (words.length > 1) {
// Handle the last word with an "and"
sb.append(" and ").append(words[1])
}
}
you don't need to use List and ListIterator (in this case!)
this is my solution!
ps: I don't undestand why the method is Static, i think in this casa is not necessary because we don't work on any static variables.
public static String formatWords(String[]words){
//Usefull to build the final resoult
StringBuilder sb = new StringBuilder();
/*start to put the word in the string builder
from the first to the last*/
for (int i = 0; i < words.length; i++) {
//put the wordat position i in string builder
sb.append(words[i]);
/*if the word is the 2 last and there are egual or more than
2 elements in words array
we can add the "and"*/
if(i==words.length-2 && words.length>=2) {
sb.append(" and ");
/*if the word is not the last put a comma
(actually we put a comma when there are more thand 3 item in words, but not in the last)
*/
}else if(i<words.length-1 ){
sb.append(", ");
}
/*if word[i] is the last of the array words we don't use nobody of the if!*/
/*this code word on 0 1,2,3 ore more word in array words!*/
}
return sb.toString();
}
replaceAll(",$", "and"); doesn't do what you think. It cannot find the last , in the string.
Try this
while(wordIter.hasNext()) {
//your code
}
if (words.length > 1) {
int indexOfLastComma = out.length() - words[words.length - 1].length();
return out.replace(indexOfLastComma - 1, indexOfLastComma, " and ").toString();
}
return out.toString();
We find the index of the last Comma and then replace it with and in its place.
Here's a fun way using Streams
String tempResult = IntStream.range(0, words.length - 1)
.mapToObj(i -> words[i])
.collect(Collectors.joining(","));
return words.length > 1 ? tempResult + " and " + words[words.length - 1] : words[0];
EDIT:
To filter out empty words, you can use a filter. Now checking words.length > 1 at the end will no longer work (since it can have empty strings). So, I'm checking if the tempResult has atleast one ,.
Here is a complete solution
String tempResult = Arrays.stream(words)
.filter(word -> !word.isEmpty())
.collect(Collectors.joining(","));
int indexOfLastComma = tempResult.lastIndexOf(',');
return indexOfLastComma != -1 ? tempResult.substring(0, indexOfLastComma) + " and "
+ tempResult.substring(indexOfLastComma + 1): tempResult;
It creates substring - so not the most efficient solution.
I've been really struggling with a programming assignment. Basically, we have to write a program that translates a sentence in English into one in Pig Latin. The first method we need is one to tokenize the string, and we are not allowed to use the Split method usually used in Java. I've been trying to do this for the past 2 days with no luck, here is what I have so far:
public class PigLatin
{
public static void main(String[] args)
{
String s = "Hello there my name is John";
Tokenize(s);
}
public static String[] Tokenize(String english)
{
String[] tokenized = new String[english.length()];
for (int i = 0; i < english.length(); i++)
{
int j= 0;
while (english.charAt(i) != ' ')
{
String m = "";
m = m + english.charAt(i);
if (english.charAt(i) == ' ')
{
j++;
}
else
{
break;
}
}
for (int l = 0; l < tokenized.length; l++) {
System.out.print(tokenized[l] + ", ");
}
}
return tokenized;
}
}
All this does is print an enormously long array of "null"s. If anyone can offer any input at all, I would reallllyyyy appreciate it!
Thank you in advance
Update: We are supposed to assume that there will be no punctuation or extra spaces, so basically whenever there is a space, it's a new word
If I understand your question, and what your Tokenize was intended to do; then I would start by writing a function to split the String
static String[] splitOnWhiteSpace(String str) {
List<String> al = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (char ch : str.toCharArray()) {
if (Character.isWhitespace(ch)) {
if (sb.length() > 0) {
al.add(sb.toString());
sb.setLength(0);
}
} else {
sb.append(ch);
}
}
if (sb.length() > 0) {
al.add(sb.toString());
}
String[] ret = new String[al.size()];
return al.toArray(ret);
}
and then print using Arrays.toString(Object[]) like
public static void main(String[] args) {
String s = "Hello there my name is John";
String[] words = splitOnWhiteSpace(s);
System.out.println(Arrays.toString(words));
}
If you're allowed to use the StringTokenizer Object (which I think is what the assignment is asking, it would look something like this:
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
which will produce the output:
this
is
a
test
Taken from here.
The string is split into tokens and stored in a stack. The while loop loops through the tokens, which is where you can apply the pig latin logic.
Some hints for you to do the "manual splitting" work.
There is a method String#indexOf(int ch, int fromIndex) to help you to find next occurrence of a character
There is a method String#substring(int beginIndex, int endIndex) to extract certain part of a string.
Here is some pseudo-code that show you how to split it (there are more safety handling that you need, I will leave that to you)
List<String> results = ...;
int startIndex = 0;
int endIndex = 0;
while (startIndex < inputString.length) {
endIndex = get next index of space after startIndex
if no space found {
endIndex = inputString.length
}
String result = get substring of inputString from startIndex to endIndex-1
results.add(result)
startIndex = endIndex + 1 // move startIndex to next position after space
}
// here, results contains all splitted words
String english = "hello my fellow friend"
ArrayList tokenized = new ArrayList<String>();
String m = "";
int j = 0; //index for tokenised array list.
for (int i = 0; i < english.length(); i++)
{
//the condition's position do matter here, if you
//change them, english.charAt(i) will give index
//out of bounds exception
while( i < english.length() && english.charAt(i) != ' ')
{
m = m + english.charAt(i);
i++;
}
//add to array list if there is some string
//if its only ' ', array will be empty so we are OK.
if(m.length() > 0 )
{
tokenized.add(m);
j++;
m = "";
}
}
//print the array list
for (int l = 0; l < tokenized.size(); l++) {
System.out.print(tokenized.get(l) + ", ");
}
This prints, "hello,my,fellow,friend,"
I used an array list since at the first sight the length of the array is not clear.
I have to write a program that reads a list of dictionary words from a file.
Subsequently, the characters of each word are put into alphabetical order and stored in the original array. (For example: Batman would become aabmnt).
Now, here is what I've done so far:
public static String[] alphabeticalOrder(String[] s)
{
//
// Sort each individual string element by alphabetical order
//
for (int i = 0; i < s.length; i++)
{
String wordSt = s[i];
char[] word = wordSt.toCharArray();
Arrays.sort(word);
s[i] = new String(word);
}
return s;
}
The call in main is simply: String[] alphaOrder = alphabeticalOrder(dictionary);
However, whenever I run the program, I get a NullPointerException and I can't seem to figure out why.
Changing s[i] to s[0] made me skip the error, but I need to convert all elements in the String, not just the first.
What is going wrong?
This can only happen if your string array has null elements, as Zavior commented.
Change your code to this:
public static String[] alphabeticalOrder(String[] s)
{
//
// Sort each individual string element by alphabetical order
//
for (int i = 0; i < s.length; i++)
{
String wordSt = s[i];
if(wordSt == null) continue;
char[] word = wordSt.toCharArray();
Arrays.sort(word);
s[i] = new String(word);
}
return s;
}
From what I see, NullPointerEception can happen only if one of the elements of the passed String array is null. To debug it, just do a null check before calling wordSt.toCharArray():
if (wordSt == null) {
System.out.println("Null encountered at index: " + i + ". Skipping this element...");
continue;
}
char[] word = wordSt.toCharArray();
This will help you figure out what is wrong with the input, and take any necessary steps to prevent it if this is not expected.
As everyone has pointed out, you might encounter NullPointerException when wordSt is null. Yet another point where you might encounter null is when String[] s itself is null(rare but possible). So I would suggest-
public static String[] alphabeticalOrder(String[] s)
{
if(s == null || s.length == 0) return s;
for (int i = 0; i < s.length; i++) {
if(s[i] != null) {
char[] word = s[i].toCharArray();
Arrays.sort(word);
s[i] = new String(word);
}
}
return s;
}
Hope this helps.
Im trying to reverse characters in a sentence without using the split function. Im really close but I am missing the final letter. Can some one please point me in the right direction? Right now it prints "This is a new sentence" as "sihT si a wen cnetnes" Also I included if(start == 0) because the program would skip the initial space character, but I don't understand why?
static String reverseLetters(String sentence)
StringBuilder reversed = new StringBuilder("");
int counter = 0;
int start = 0;
String word;
for(int i = 0; i <= sentence.length()-1 ; i++ )
{
if(sentence.charAt(i)== ' '|| i == sentence.length()-1 )
{
StringBuilder sb = new StringBuilder("");
sb.append(sentence.substring(start,i));
if(start == 0)
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
reversed.append(' ');
}
else
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
}
}
return reversed.toString();
}
static String reverseChar (String word)
{
StringBuilder b = new StringBuilder("");
for(int idx = word.length()-1; idx >= 0; idx -- )
{
b.append(word.charAt(idx));
}
return b.toString();
}
start means wordStart. As i points to the space, the next wordStart should point after i.
Hence the last i should point after the last word char, should be length()
the if-then-else is too broad; a space has to be added in one case: i pointing at the space.
One could loop unconditionally, and on i == length() break in the middle of the loop code.
I think the error lies in the index, the for should be
for(int i = 0; i <= sentence.length() ; i++ )
Then if should be:
if (sentence.charAt(i==0?0:i-1)== ' '|| i == sentence.length() )
For me the error will be that the substring(start,i) for the last one i should be sentence.length instead of sentence.length-1, so this would solve it.
Substring is open in the last index, so if you put substring(1, 10) will be substring from 1 to 9. That might be the problem with last word.
The thing with the first space is also the problem with substring, let's say you're reading "this is..." the first time it will do a subtring with start=0 and i = 4 so you expect "this " but it really is "this". The next reading, with start=4 and i=7 will be " is".
So with the change of the index you should be able to remove the if/else with start==0 too.
Another option
private String reverse (String originalString) {
StringBuilder reverseString = new StringBuilder();
for (int i = originalString.length() - 1; i >= 0; i--) {
reverseString.append(originalString.charAt(i));
}
return reverseString.toString();
}
String reverseString = "This is a new sentence";
System.out.println(new StringBuffer(reverseString).reverse().toString());
Syso prints : ecnetnes wen a si sihT
Put
i <= sentence.length()
In your for loop and change the if to:
if(i == sentence.length() || sentence.charAt(i)== ' ')
as
substring(start,i)
Returns the string up to i, not included.
import java.util.Stack;
public class Class {
public static void main(String[] args) {
String input = "This is a sentence";
char[] charinput = input.toCharArray();
Stack<String> stack = new Stack<String>();
for (int i = input.length() - 1; i >= 0; i--) {
stack.push(String.valueOf(charinput[i]));
}
StringBuilder StackPush = new StringBuilder();
for (int i = 0; i < stack.size(); i++) {
StackPush.append(stack.get(i));
}
System.out.println(StackPush.toString());
}
}
Not a split to be seen.