patternjavaModerate
Anagrams for a given input
Viewed 0 times
inputgivenforanagrams
Problem
This question is the first draft, my new revised code is here:
Anagrams for a given input 2.0
Here is my code that I wrote, which basically lists the anagrams for a given input.
I did this by reading each line in my dictionary file and comparing it to the anagram. Only if it matched did I add it to the
I compared the words by first checking the length of both words, and then if they matched I put put each word into a list and then sorted the
The function of my
What I would like are some critiques on my work and what I should/could have done differently, especially pertaining to semantic efficiency, code correctness, common practices that I may be unaware of, and code efficiency.
This is only my second project, so I want to learn from it to become a better programmer. That's why I'm asking.
The methods are in the order they are called in:
(Note that I split the code up to make it easier to see, all the methods are inside the Anagramatic Class)
-
-
```
private static String input() {
String input;
input = JOptionPane.showInputDialog(null,
"Enter the Word or words you would like to
Anagrams for a given input 2.0
Here is my code that I wrote, which basically lists the anagrams for a given input.
I did this by reading each line in my dictionary file and comparing it to the anagram. Only if it matched did I add it to the
list, instead of adding all the words to the list and then sorting through them.I compared the words by first checking the length of both words, and then if they matched I put put each word into a list and then sorted the
list, then I compared the two lists using the equals() function. And iterated my counter.The function of my
getOutPut() was just to neaten up the printout.What I would like are some critiques on my work and what I should/could have done differently, especially pertaining to semantic efficiency, code correctness, common practices that I may be unaware of, and code efficiency.
This is only my second project, so I want to learn from it to become a better programmer. That's why I'm asking.
The methods are in the order they are called in:
(Note that I split the code up to make it easier to see, all the methods are inside the Anagramatic Class)
package anagramatic;
/**
* IDE : NETBEANS
* Additional Libraries : Guava
* @author KyleMHB
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class Anagramatic {
static int k;-
public static void main(String[] args) throws FileNotFoundException{
String anagram;
anagram=input();
ArrayList words=readFile(anagram);
String output= getOutPut(words);
JOptionPane.showMessageDialog(null,
"The anagram "+anagram+" has "+k+" matches, they are:\n\n"+output);
}//PVSM-
```
private static String input() {
String input;
input = JOptionPane.showInputDialog(null,
"Enter the Word or words you would like to
Solution
I'll focus on the heart of your solution first, which is your
Points to note:
Next, let's look at
Points to note:
Finally:
Observations:
readFile() method. Here's how I would write it:public static List anagramsInFile(String word, File f)
throws FileNotFoundException {
char[] canonical = canonicalize(original);
ArrayList anagrams = new ArrayList();
try (Scanner s = new Scanner(f)) {
while (s.hasNext()) {
String candidate = s.next();
if ( (candidate.length() == word.length()) &&
(Arrays.equals(canonical, canonicalize(candidate))) ) {
anagrams.add(candidate);
}
}
}
return anagrams;
}
private static char[] canonicalize(String original) {
char[] array = original.toCharArray();
Arrays.sort(array);
return array;
}Points to note:
- Naming is important.
handleFile()is vague;anagramsInFile()is meaningful. Also, I findanagto be confusing parameter name.
- Hard-coding the filename inside the method is a bad idea.
- Unless the caller has a reason to require an
ArrayList, your method signature should just commit to returning some kind ofList. Better yet, consider returning aSet.
- You only have to canonicalize the original string once, not once per word in the file.
- Canonicalization deserves a helper method, since you have to do it to both the original string and to the contents of the file.
- Canonicalizing to a
char[]avoids working character by character, since you can take advantage ofString.toCharArray(). It's probably more efficient as well.
- There's no point in maintaining
k: it's just thesize()of the returned list. Maintainingkas a class variable is particularly egregious, as there's no reason for that count to be part of the state of the class.
- If your blocks are so lengthy and deeply nested that you need comments on the closing braces, consider that a Bad Code Smell and address that issue instead. (By the way, your braces were misaligned, which causes confusion that even your close-brace comments can't compensate for.)
Next, let's look at
getOutPut(). Here's how I would write it:private static String formatOutput(List words) {
StringBuilder out = new StringBuilder('[');
int wordsPrinted = 0;
Iterator w = words.iterator();
while (w.hasNext()) {
out.append(w.next());
if (w.hasNext()) {
out.append((++wordsPrinted % 8 == 0) ? "\n" : ", ");
}
}
return out.append(']').toString();
}Points to note:
- When concatenating so many strings, you really need to use a
StringBuilder. Repeatedstring + stringwould create a temporary string each time.
- Your output is buggy: you drop every eighth word, replacing it with a newline.
- Be careful with edge cases: your code crashes when
wordsis empty.
- Try to structure your code so it's obvious that certain properties hold true. For example, in my solution, you can see that every word gets printed (because if
.hasNext()is true, the next word will get appended). You can also see that every word except the last word is followed by a delimiter (either newline or comma).
- Avoid cryptically named variables like
xandy. In fact, you don't even usey.
- Naming your result
wordzwhen there's another variable namedwordsmakes the code a pain to read.
Finally:
public static void main(String[] args) throws FileNotFoundException{
String word = input("Enter the word or words you would like to be processed");
List anagrams = anagramsInFile(word, new File("words.txt"));
display(String.format("The word %s has %d matches. They are:\n\n%s",
word, anagrams.size(), formatOutput(anagrams)));
}
private static String input(String prompt) {
return JOptionPane.showInputDialog(null, prompt);
}
private static void display(String message) {
JOptionPane.showMessageDialog(null, message);
}Observations:
- I've decomposed the work differently. There's
input()anddisplay(), which are analogous to each other, and encapsulate the Swing UI. (If you ever want to convert the program to work in the text console, you just modify those functions.)
- More importantly, you can now see at a glance what the whole program does just by looking at
main(). Note that all string constants are there as well: the prompt, the filename, and the output.
- Don't declare any more variables than you need to. If possible, when you declare variables, assign them in the same statement.
- Use
String.format().
Code Snippets
public static List<String> anagramsInFile(String word, File f)
throws FileNotFoundException {
char[] canonical = canonicalize(original);
ArrayList<String> anagrams = new ArrayList<String>();
try (Scanner s = new Scanner(f)) {
while (s.hasNext()) {
String candidate = s.next();
if ( (candidate.length() == word.length()) &&
(Arrays.equals(canonical, canonicalize(candidate))) ) {
anagrams.add(candidate);
}
}
}
return anagrams;
}
private static char[] canonicalize(String original) {
char[] array = original.toCharArray();
Arrays.sort(array);
return array;
}private static String formatOutput(List<String> words) {
StringBuilder out = new StringBuilder('[');
int wordsPrinted = 0;
Iterator<String> w = words.iterator();
while (w.hasNext()) {
out.append(w.next());
if (w.hasNext()) {
out.append((++wordsPrinted % 8 == 0) ? "\n" : ", ");
}
}
return out.append(']').toString();
}public static void main(String[] args) throws FileNotFoundException{
String word = input("Enter the word or words you would like to be processed");
List<String> anagrams = anagramsInFile(word, new File("words.txt"));
display(String.format("The word %s has %d matches. They are:\n\n%s",
word, anagrams.size(), formatOutput(anagrams)));
}
private static String input(String prompt) {
return JOptionPane.showInputDialog(null, prompt);
}
private static void display(String message) {
JOptionPane.showMessageDialog(null, message);
}Context
StackExchange Code Review Q#32204, answer score: 10
Revisions (0)
No revisions yet.