简体   繁体   中英

Nested Loops and Arrays (Frequency Analysis)

I was wondering if I could get some help with with properly incrementing values to arrays. The point of this program is to analyze the frequency of individual letters in a text file, and record them in an array.

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FrequencyAnaylsis 
{
public static String[] alphabet = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
public static int[] alphabetFrequency = new int[26];
public static int[] alphabetPercentage = new int[26];

FrequencyAnaylsis()
{
}

public static void getFileAndFrequency() throws FileNotFoundException
{
    File plaintext = new File("subplaintext");
    Scanner inFile = new Scanner(plaintext);

    for (int i = 0; i < 26; i++) //specifies the index of alphabet (the letter the program is looking for)
    {   
        while (inFile.hasNext()) //is true when the document has another word following the previous
        {
            String[] lettersToCompare = inFile.next().toLowerCase().split("(?!^)"); //splits the specified word into a String array

            for (int stringIndex = 0; stringIndex < lettersToCompare.length; stringIndex++) //loops through the index (individual letters) of the split word
            {
                if (lettersToCompare[stringIndex].equals(alphabet[i])) //if letter specified in split word equals letter specified in alphabet
                {
                    alphabetFrequency[i]++; //add one to the frequency array in the same index as the index in alphabet
                }
            }
        }   
    }
}

public static void getPercentage()
{
    int alphabetFrequencyTotal = 0;

    for (int i = 0; i < 26; i++)
    {
        alphabetFrequencyTotal =+ alphabetFrequency[i];
    }

    for (int i = 0; i < 26; i++)
    {
        alphabetPercentage[i] = alphabetFrequency[i]/alphabetFrequencyTotal;
    }
}

public static void printData()
{
    for (int i = 0; i < 26; i++)
    {
        System.out.println(alphabetFrequency[i]);
    }
}

public static void main(String[] args) throws FileNotFoundException
{
    FrequencyAnaylsis.getFileAndFrequency();
    //FrequencyAnaylsis.getPercentage();
    FrequencyAnaylsis.printData();

}
}

When the program reads this sentence: "Five score years ago, a great American, in whose symbolic shadow we stand, signed the Emancipation Proclamation.", it outputs the following:

12
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

It's able to count the characters correctly in the case of "a", but it doesn't do so for any other letter. Why is that? Any help would be appreciated.

You problem is that you're trying to go through the file once for each letter of the English alphabet with this:

public static void getFileAndFrequency() throws FileNotFoundException
{
    File plaintext = new File("subplaintext");
    Scanner inFile = new Scanner(plaintext);

    for (int i = 0; i < 26; i++) //specifies the index of alphabet (the letter the program is looking for)
    {   
        while (inFile.hasNext()) //is true when the document has another word following the previous
        {
            String[] lettersToCompare = inFile.next().toLowerCase().split("(?!^)"); //splits the specified word into a String array

            for (int stringIndex = 0; stringIndex < lettersToCompare.length; stringIndex++) //loops through the index (individual letters) of the split word
            {
                if (lettersToCompare[stringIndex].equals(alphabet[i])) //if letter specified in split word equals letter specified in alphabet
                {
                    alphabetFrequency[i]++; //add one to the frequency array in the same index as the index in alphabet
                }
            }
        }   
    }
}

After the outer loop ( for (int i = 0; i < 26; i++) ) has run once, you're at the end of file, so all subsequent runs will act as though the file is empty.

A simple fix is to change the order of the loops:

public static void getFileAndFrequency() throws FileNotFoundException
{
    File plaintext = new File("subplaintext");
    Scanner inFile = new Scanner(plaintext);

    while (inFile.hasNext()) //is true when the document has another word following the previous
    {   
        String[] lettersToCompare = inFile.next().toLowerCase().split("(?!^)"); //splits the specified word into a String array

        for (int i = 0; i < 26; i++) //specifies the index of alphabet (the letter the program is looking for)
        {
            for (int stringIndex = 0; stringIndex < lettersToCompare.length; stringIndex++) //loops through the index (individual letters) of the split word
            {
                if (lettersToCompare[stringIndex].equals(alphabet[i])) //if letter specified in split word equals letter specified in alphabet
                {
                    alphabetFrequency[i]++; //add one to the frequency array in the same index as the index in alphabet
                }
            }
        }   
    }
}

However, you're doing way too much in the inner loop. As @Jägermeister points out, you'd be better off either using a Map (eg HashMap ) or utilize that you can simply assign the indices in your alphabetFrequency array directly:

public static void getFileAndFrequency() throws FileNotFoundException
{
    File plaintext = new File("subplaintext");
    Scanner inFile = new Scanner(plaintext);

    while (inFile.hasNext()) //is true when the document has another word following the previous
    {   
        String[] lettersToCompare = inFile.next().toLowerCase().split("(?!^)"); //splits the specified word into a String array

        for (int stringIndex = 0; stringIndex < lettersToCompare.length; stringIndex++) //loops through the index (individual letters) of the split word
        {
            char ch = lettersToCompare[stringIndex].charAt(0);
            if (ch >= 'a' && ch <= 'z')
                alphabetFrequency[ch-'a']++; //add one to the frequency array in the same index as the index in alphabet
        }   
    }
}

Example of using a Map :

public static Map<Char,Integer> getFileAndFrequency() throws FileNotFoundException
{
    Map<Char,Integer> frequencyMap = new HashMap<Char,Integer>();
    File plaintext = new File("subplaintext");
    Scanner inFile = new Scanner(plaintext);

    while (inFile.hasNext()) //is true when the document has another word following the previous
    {   
        String[] lettersToCompare = inFile.next().toLowerCase().split("(?!^)"); //splits the specified word into a String array

        for (int stringIndex = 0; stringIndex < lettersToCompare.length; stringIndex++) //loops through the index (individual letters) of the split word
        {
            char ch = lettersToCompare[stringIndex].charAt(0);
            Integer frequency = frequencyMap.get(ch);
            if (frequency ==null) {
               frequency = 0;
            }
            frequency += 1;
            frequencyMap.put(ch, frequency);
        }   
    }
    return frequencyMap;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM