ArrayList is not being populated - java

I'm a bit of a Java noob, so any help is appreciated. I have a method that is supposed to take a char value and an Arraylist of words in alphabetical order, and return all of the strings in the list that start with the same letter as the char. I'm not getting any error messages, but my method keeps returning an empty ArrayList. Why isn't my List being filled?
public String singlePhrase(char c, ArrayList<String> wordList){
ArrayList<String> words = new ArrayList<String>();
for (int i = 0; i < wordList.size(); i++) {
if (wordList.get(i).charAt(0) == c){
words.add(wordList.get(i));
}
}
return "Size: "+words.size() + " "+c;
}

If you wanted to return an ArrayList of words use the following:
public ArrayList<String> singlePhrase(char c, ArrayList<String> wordList) {
ArrayList<String> words = new ArrayList<String>();
for (int i = 0; i < wordList.size(); i++) {
if (Character.toLowerCase(wordList.get(i).charAt(0)) == Character.toLowerCase(c)) {
words.add(wordList.get(i));
}
}
return words;
}
Note that it compares the lowercase version of both characters.

Thank you guys for all the help, but the answer was way too simple. In the .txt file that was being parsed, all the strings began with uppercase letters. The test input was all lowercase, resulting in the '==' being false and the if() statement never being triggered.

Related

How to locate simple words amongst compound/simple words using Java?

I have a list of words that have both 'simple' and 'compound' words in them, and would like to implement an algorithm that prints out a list of words without the compound words that are made up of the simple words.
Sampel input:
chat, ever, snapchat, snap, salesperson, per, person, sales, son, whatsoever, what, so
Desired output:
chat, ever, snap, per, sales, son, what, so
I have written the following, but am stuck as to how to take it on from here:
private static String[] find(String[] words) {
ArrayList<String> alist = new ArrayList<String>();
Set<String> r1 = new HashSet<String>();
for(String s: words){
alist.add(s);
}
Collections.sort(alist,new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
int count= 0;
for(int i=0;i<alist.size();i++){
String check = alist.get(i);
r1.add(check);
for(int j=i+1;j<alist.size();j++){
String temp = alist.get(j);
//System.out.println(check+" "+temp);
if(temp.contains(check) ){
alist.remove(temp);
}
}
}
System.out.println(r1.toString());
String res[] = new String[r1.size()];
for(String i:words){
if(r1.contains(i)){
res[count++] = i;
}
}
return res;
}
Any guidance/insight or suggestions to a better approach would be appreciated.
I tried to go through your code, looks like "son" is not in your output. I believe it failed because of this line:
if(temp.contains(check)) { <-- wrong check.
alist.remove(temp);
}
So instead of simply checking if temp.contains(check), you should have a small loop that does the following:
does temp start with check?
if 1) passed, then let temp = temp.substring(check.length), then go back to 1) again, until temp == "";
Another implementation would be setting up a trie (https://en.wikipedia.org/wiki/Trie) and check using that?
sort the word list based on word length
foreach of the word, if the word is not in the trie, add it to the trie. otherwise, this is either a dup or a compound word
output the trie into a list of words using DFS.
step 1 make sure that when u check for a compound word, its simple word is already in the trie.
I didn't try to find the bug in your code, but rather wrote my own impl using a simple loop and a recursive helper method:
private static String[] find(String[] array) {
Set<String> words = new LinkedHashSet<>(Arrays.asList(array));
Set<String> otherWords = new HashSet<>(words);
for (Iterator<String> i = words.iterator(); i.hasNext(); ) {
String next = i.next();
otherWords.remove(next);
if (isCompound(next, otherWords)) {
i.remove();
} else {
otherWords.add(next);
}
}
return words.stream().toArray(String[]::new);
}
private static boolean isCompound(String string, Set<String> otherWords) {
if (otherWords.contains(string)) {
return true;
}
for (String word : otherWords) {
if (string.startsWith(word)) {
return isCompound(string.replaceAll("^" + word, ""), otherWords);
}
if (string.endsWith(word)) {
return isCompound(string.replaceAll(word + "$", ""), otherWords);
}
}
return false;
}
See live demo.
This produces your desired output, which requires preserving word order.
Explanation
A compound word is comprised solely of other words in the list. Importantly, this implies that compound words both start and end with other words. Rather than search for other words at every position in a word, we can use this fact to only check the start/end , which greatly simplifies the code.
Thus: for each word in the list, if it start/ends with another word, remove that word and repeat the process until there's nothing left, at which point you know the word is compound.
A set of "other words", which is the full set with the current word removed, is passed to the helper method to further simplify the code.
Here is my straightforward n^2 solution:
static String[] simpleWords(String[] words) {
String[] result;
HashSet<Integer> map = new HashSet<>();
for(int i = 0; i < words.length; i++) {
String word = words[i];
for(int j = 0; j < words.length; j++) {
if(j != i) {
word = word.replaceAll(words[j], "");
}
}
if(!word.equals("")) {
map.add(i);
}
}
result = new String[map.size()];
int i = 0;
for(int index: map) {
result[i] = words[index];
i++;
}
return result;
}

Java how to compare unordered string arrays [duplicate]

This question already has answers here:
how to compare two string arrays without java utils
(3 answers)
Closed 7 years ago.
I have to arrays of string
Array 1
Dog
Cat
Mouse
Chicken
Array 2
Cat
Dog
Mouse
Chicken
How can I check if the arrays comtains the same elements (order does not matter)
I guess I should first sort the array and than to compare
I am looking for a boolean answer
EDIT using Java utils is an option for me, I am just not familiar with JAVA enough
Just sort them both and iterate over the elements to compare them all:
public boolean compareStringArrays(String[] arr1, String[] arr2) {
if (arr1.length != arr2.length)
return false;
String[] arr1Copy = arr1.clone();
String[] arr2Copy = arr2.clone();
Arrays.sort(arr1Copy);
Arrays.sort(arr2Copy);
for (int i=0; i<arr1Copy.length; i++) {
if (!arr1Copy[i].equals(arr2Copy[i]))
return false;
}
return true;
}
Note that I make copies of the arrays here: this is so the original order of the arrays passed in is preserved. There's also an optimisation to check the lengths are the same first, as if one array has more elements than the other they are obviously not equal.
EDIT
you can also use Arrays.equals() instead of a for loop (which I originally didn't think of but seems obvious now), so you could achieve this with a one-liner:
Arrays.equals(Arrays.sort(arr1.clone()), Arrays.sort(arr2.clone()));
ArrayList<String> arrList1 = new ArrayList<>(Arrays.asList(arr1));
ArrayList<String> arrList2 = new ArrayList<>(Arrays.asList(arr2));
Collections.sort(arrList1);
Collections.sort(arrList2);
if (Arrays.equals(arrList1.toArray(), arrList2.toArray())) {
//They have exactly the same elements
}
EDIT:
Old answer:
ArrayList<String> arrList1 = new ArrayList<>(Arrays.asList(arr1));
ArrayList<String> arrList2 = new ArrayList<>(Arrays.asList(arr2));
if (arrList1.containsAll(arrList2) && arrList2.containsAll(arrList1)) {
//They have the same elements, not necessarily the same number
}
The top answer will tell you if they both contain the same elements, as well as if they have the same number, Bottom answer will tell you if they both have the same elements, but doesn't tell you if any elements are duplicated
EDIT again:
Firstly I posted:
if (arrList1.containsAll(arrList2) && arrList2.containsAll(arrList1)
&& arrList1.size() == arrList2.size())
Checking the size is equal is redundant, since if we have the lists:
Cat
Cat
Dog
and
Cat
Dog
Dog
The expression would evaluate to true, but they do not have exactly the same elements
Here is the method:
public boolean compareArray(){
boolean isSameArray=false;
String[] arr1={"Dog","Cat","Mouse","Chicken"};
String[] arr2={"Cat","Dog","Mouse","Chicken"};
Arrays.sort(arr1);
Arrays.sort(arr2);
if(Arrays.equals(arr1, arr2)){
isSameArray=true;
}else{
isSameArray=false;
}
return isSameArray;
}
That is very easy. Just do like this:
ArrayList<String> firstArray=new ArrayList<>();
ArrayList<String> secondArray=new ArrayList<>();
firstArray.add("Dog");
firstArray.add("Cat");
firstArray.add("Mouse");
firstArray.add("Chicken");
secondArray.add("Cat");
secondArray.add("Dog");
secondArray.add("Mouse");
secondArray.add("Chicken");
boolean areEqual=firstArray.containsAll(secondArray);
if(areEqual)
System.out.println("Voila!");
else
System.out.println("Oppps!");
May ways how to do that
- probably the best way is to make sort and compare Arrays like Collections(Arrays.sort(arrayToSort)), objects (Arrays.equals(arr1,arr2))
- another way is just iterate over 1st and 2nd array and try to find items one by one (bad idea, not such effective, but good to understand and explain)- something like following:
String[] arr1={"Dog","Cat","Mouse","Chicken"};
//String[] arr2={"Dog","Mouse","Chicken"}; //FALSE
String[] arr2={"Cat","Dog","Mouse","Chicken"}; //TRUE
boolean foundAll = true;
if(arr1.length != arr2.length){
foundAll = false;
}else{
for (int i = 0; i < arr1.length; i++) {
boolean foundActual = false;
for (int j = 0; j < arr2.length; j++) {
if(arr1[i].equals(arr2[j])){
foundActual = true;
break;
}
System.out.println("arr1 elem: " + arr1[i] + " arr2 elem: "+ arr2[j]);
}
System.out.println("\n");
if(!foundActual){
foundAll = false;
break;
}
}
}
System.out.println("found all: " + foundAll);
}
String arr1[] = {//your content goes here};
String arr2[] = {//your content goes here};
Arrays.sort(arr1);
Arrays.sort(arr2);
if(arr1.length != arr2.length){
retrn false;
}else{
boolean isSimilar = true;
for(int i=0; i< arr1.length; i++){
if(!(arr1[i].equals(arr2[i]))){
isSimilar = false;
}
}
}
return isSimilar;

removing duplicated words from an array

I am trying to remove duplicated words from an array, and I keep getting null values. I'm not allowed to use java sorting methods so I have to develop my own. Here's my code:
public class Duplicate{
public static void main(String[] args){
String[] test = {"a", "b", "abvc", "abccc", "a", "bbc", "ccc", "abc", "bbc"};
removeDuplicate(test);
}
public static String[] removeDuplicate(String[] words){
boolean [] isDuplicate = new boolean[words.length];
int i,j;
String[] tmp = new String[words.length];
for (i = 0; i < words.length ; i++){
if (isDuplicate[i])
continue;
for(j = 0; j < words.length ; j++){
if (words[i].equals(words[j])) {
isDuplicate[j] = true;
tmp[i] = words[i];
}
}
}
for(i=0;i<words.length;i++)
System.out.println(tmp[i]);
return tmp;
}
}
I tried doing
if(words == null)
words == "";
But it doesn't work. I also want to return the tmp array with a new size.
For example, test array length = 9, after removing the duplicates,I should get a new array with a length of 7.Thank you for your help.
EDIT:
result i get:
a
b
abvc
abccc
null
bbc
ccc
abc
null
You're getting nulls because the result array contains fewer words than the input array. However, you're constructing the arrays of the same length.
You don't have to sort to solve this problem. However, if you're not allowed to use the tools provided by java.utils, then this is either a poorly contrived test question or whomever told you not to use the Java utility classes is poorly informed.
You can solve without sorting by doing (assuming Java 1.5+):
public class Duplicate {
public static void main(String[] args) {
String[] test = {"a", "b", "abvc", "abccc", "a", "bbc", "ccc", "abc", "bbc"};
String[] deduped = removeDuplicate(test);
print(deduped);
}
public static String[] removeDuplicate(String[] words) {
Set<String> wordSet = new LinkedHashSet<String>();
for (String word : words) {
wordSet.add(word);
}
return wordSet.toArray(new String[wordSet.size()]);
}
public static void print(String[] words) {
for (String word : words) {
System.out.println(word);
}
}
}
The output will be:
a
b
abvc
abccc
bbc
ccc
abc
I would go for hashset to remove duplicates, it will remove duplicates since hash function for the same string will give same value, and duplicates will be eliminated. Then you can convert it to a string.
I would recommend doing this with a different approach. If you can use an ArrayList, why not just create one of those, and add the non-duplicate values to it, like this:
ArrayList<String> uniqueArrayList = new ArrayList<String>();
for(int i = 0; i < words.length; i++){
if(!uniqueArrayList.contains(words[i])){ // If the value isn't in the list already
uniqueArrayList.add(words[i]);
}
}
Now, you have an array list of all of your values without the duplicates. If you need to, you can work on converting that back to a regular array.
EDIT
I really think you should use the above option if you can, as there is no clean or decently efficient way to do this only using arrays. However, if you must, you can do something like this:
You can use the code you have to mark values as null if they are duplicates, and also create a counter to see how many unique values you have, like this:
int uniqueCounter = 0;
for(int i = 0; i < isDuplicate.length; i++){
if(!isDuplicate[i]){
uniqueCounter++;
}
}
Then, you can create a new array of the size of unique items, and loop through the words and add non-duplicate values.
String[] uniqueArray = new String[uniqueCounter];
int uniqueIndex = 0;
int wordsIndex = 0;
while(index < uniqueArray.length){
// Check if words index is not a duplicate
if(!isDuplicate[wordsIndex]){
// Add to array
uniqueArray[uniqueIndex] = words[wordsIndex];
uniqueIndex++; // Need to move to next spot in unique.
}
// Need to move to next spot in words
wordsIndex++;
}
Again, I HIGHLY recommend against something like this. It is very poor, and pains me to write, but for the sake of example on how it could be done using an array, you can try it.
I don't have the time to write functioning code, but I would reccomend to first sort the array using Arrays.sort(stringArray) and then loop throug the array coparing one string to the previous. Strings that match the previous one are duplicates.
Note: This method is probably not the fastest one and though only should be used on small arrays or in tasks where performance does not matter.
What about this approach?
public static String[] removeDuplicate(String[] words){
// remember which word is a duplicate
boolean[] isDuplicate = new boolean[words.length];
// and count them
int countDuplicate = 0;
for (int i = 0; i < words.length ; i++){
// only check "forward" because "backwards checked" duplicates have been marked yet
for(int j = i + 1; j < words.length ; j++){
if (words[i].equals(words[j])) {
isDuplicate[j] = true;
countDuplicate++;
}
}
}
// collect non-duplicate strings
String[] tmp = new String[words.length - countDuplicate];
int j = 0;
for (int i = 0; i < isDuplicate.length; i++) {
if (isDuplicate[i] == false) {
tmp[j] = words[i];
j++;
}
}
// and return them
return tmp;
}

Java Isomorphic Code

I am kind of stuck on this java problem involving returning the number of isomorphic pairs in an array of Strings. The code I have written keeps returning incorrect number of isomorphic word pairs.
The definition of isomorphic words is given as follows: Two words are called isomorphic if the letters in one word can be remapped to get the second word. Remapping a letter means replacing all occurrences of it with another letter. The ordering of the letters remains unchanged. No two letters may map to the same letter, but a letter may map to itself.
For example, the words "abca" and "zbxz" are isomorphic because we can map 'a' to 'z', 'b' to 'b' and 'c' to 'x'.
I am not inlcuding the getMap method which I call in the function. The getMap method take any string as input, and returns a map where the keys are the letters in the string, and the corresponding values are the number of times the letter appears in the string.
public class IsomorphicWords {
public int countPairs(String[] words) {
Set <String> pairs = new HashSet<String>();
for (String word:words){
Map noOfOccurencesOfEachLetter= getMap(word);
ArrayList<Integer> valuesFromFirstWord = new ArrayList<Integer>(noOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromFirstWord);
java.util.List<String> list = new ArrayList<String>(Arrays.asList(words));
list.remove(word);
String[] oneLessWord = list.toArray(new String[words.length-1]);
for(String secondWord:oneLessWord){
Map secondNoOfOccurencesOfEachLetter = getMap(secondWord);
ArrayList<Integer> valuesFromSecondWord = new ArrayList<Integer>(secondNoOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromSecondWord);
if (valuesFromFirstWord.equals(valuesFromSecondWord)){
pairs.add(""+word+","+secondWord+"");
}
else{
continue;
}
}
}
return pairs.size()/2;
public Map getMap(String word){
HashMap<String,Integer> noOfOccurencesOfEachLetter= new HashMap<String,Integer>();
for (int i=0;i<word.length();i++){
char letter = word.charAt(i);
String letterInDictionary= Character.toString(letter);
if (noOfOccurencesOfEachLetter.containsKey(letterInDictionary)==true){
int count= noOfOccurencesOfEachLetter.get(letterInDictionary);
noOfOccurencesOfEachLetter.put(letterInDictionary, count+1);
}
else{
noOfOccurencesOfEachLetter.put(letterInDictionary, 1);
}
}
return noOfOccurencesOfEachLetter;
}
}
I'd really appreciate any feedback you can give me on this code.
Thanks,
Junaid
The reason why it gives the incorrect answer probably comes from you take the letter count, and don't look at the position that they have in both words. The first solution that comes up in me, is to create a new array in which you translate the letters to the index of the first occurrence of this letter for each word. For example: "abcd" would be "0123", "abca" would be "0120" and "fhjf" would be "0120" as well. Then you can simply compare the results. I hope this helps...
public int countPairs(String[] words) {
int isomorphicPairs = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i+1; j < words.length; j++) {
if (words[i].length() == words[j].length()) {
String tmp = new String(words[j]);
for (int k = 0; k < tmp.length(); k++)
tmp = tmp.replaceAll("" + tmp.charAt(k), "" + words[i].charAt(k));
if (words[i].equals(tmp)) isomorphicPairs++;
}
}
}
return isomorphicPairs;
}

NullPointerException adding substring from string to array list

What I'm trying to do is add a substring from a String to an ArrayList. basically adding every letter in the string to an index in the ArrayList. After that i have a print statement just to see if the letters were added to the ArrayList (thats the second for loop under makearraylisOfChosenWord). However, when i run this with or without the print statement, it gives me a NullPointerException. Is it because I'm adding the letters to the arraylist in a wrong way in the first for loop?
thanks for the help
heres the code:
String[] wordList = {"apple", "orange", "strawberry", "banana"};
String chosenWord;
//Make an array list to hold one letter of the chosen word at each index
void makeArrayListOfChosenWord(){
ArrayList<String> lettersOfChosenWord = new ArrayList<String> ();
for (int i = 0; i < chosenWord.length(); i++) {
lettersOfChosenWord.add(chosenWord.substring(i, i+1));
}
for (int i = 0; i < lettersOfChosenWord.size(); i++) {
System.out.println((lettersOfChosenWord.get(i)).toString());
}
}
//Let the game pick a random word from the word list
void setRandomWord(){
int wordListLength = wordList.length;
int pickRandomWord = (int) (Math.random() * wordListLength);
String createRandomWord = wordList[pickRandomWord];
chosenWord = createRandomWord;
System.out.printf("the word is %s letters long", chosenWord.length());
}
I was just thinking about your problem and would try to use an ArrayList of Character instead of String. This is imo ok, because you mentioned that you are splitting up a String into single Characters, so ArrayList<Character>() seems a reasonable approach.
For splitting up the String I would make use of the method toCharArray():
String str = "abcd...";
ArrayList<Character> chars = new ArrayList<Character>();
for (char c : str.toCharArray()) {
chars.add(c);
}
If you call your setRandomWord method before you call makeArrayListOfChosenWord method no NullPointerException will be thrown. No if-check is needed in your code for this condition.

Categories

Resources