Проблема древовидной карты - PullRequest
2 голосов
/ 06 января 2011

Я пытаюсь посчитать частоту слов в текстовом файле. Но я должен использовать другой подход. Например, если файл содержит BRAIN-ISCHEMIA и ISCHEMIA-BRAIN, мне нужно сосчитать BRAIN-ISCHEMIA дважды (и оставить ISCHEMIA-BRAIN) или наоборот. Вот мой кусок кода -

// Mapping of String->Integer (word -> frequency) 
    HashMap<String, Integer> frequencyMap = new HashMap<String, Integer>(); 

    // Iterate through each line of the file 
    String[] temp;
    String currentLine; 
    String currentLine2;
    while ((currentLine = in.readLine()) != null) { 

    // Remove this line if you want words to be case sensitive 
    currentLine = currentLine.toLowerCase();
    temp=currentLine.split("-");
    currentLine2=temp[1]+"-"+temp[0];

    // Iterate through each word of the current line 
    // Delimit words based on whitespace, punctuation, and quotes 
    StringTokenizer parser = new StringTokenizer(currentLine);
    while (parser.hasMoreTokens()) { 
    String currentWord = parser.nextToken(); 

    Integer frequency = frequencyMap.get(currentWord); 

    // Add the word if it doesn't already exist, otherwise increment the 
    // frequency counter. 
    if (frequency == null) { 
    frequency = 0; 
    } 
    frequencyMap.put(currentWord, frequency + 1); 
    }
    StringTokenizer parser2 = new StringTokenizer(currentLine2);
    while (parser2.hasMoreTokens()) { 
        String currentWord2 = parser2.nextToken(); 

        Integer frequency = frequencyMap.get(currentWord2); 

        // Add the word if it doesn't already exist, otherwise increment the 
        // frequency counter. 
        if (frequency == null) { 
        frequency = 0; 
        } 
        frequencyMap.put(currentWord2, frequency + 1); 

        } 
    }

    // Display our nice little Map 
    System.out.println(frequencyMap);

Но для следующего файла -

ISCHEMIA-глутамат ISCHEMIA-BRAIN Глутамат-BRAIN BRAIN-ДОПУСКАЕМ BRAIN-ДОПУСКАЕМ ДОПУСКАЕМ-BRAIN Глутамат-ISCHEMIA ISCHEMIA-глутамат

Я получаю следующий вывод-

{глутамат-мозг = 1, ишемия-глутамат = 3, ишемия-мозг = 1, глутамат-ишемия = 3, переносимость мозга = 3, ишемия головного мозга = 1, переносимость мозга = 3, глутамат мозга = 1}

Проблема во втором блоке, я думаю. Любой свет по этой проблеме будет высоко оценен.

Ответы [ 3 ]

2 голосов
/ 06 января 2011

С точки зрения алгоритма, вы можете рассмотреть следующий подход:

Для каждой строки, разделить, затем отсортировать, затем объединить (т.е. взять DEF-ABC и преобразовать в ABC-DEF. ABC-DEF будет преобразован в ABC-DEF).Затем используйте его в качестве ключа для подсчета частоты.

Если вам нужно удерживать точный исходный элемент, просто включите его в свой ключ - чтобы ключ имел: порядковый номер (повторно объединенная строка) иоригинальный.

1 голос
/ 06 января 2011

Отказ от ответственности: я украл сладкую уловку , предложенную Кевином Дей для моей реализации.

Я все еще хочу опубликовать, чтобы простовы знаете, что использование правильной структуры данных ( Multiset / Bad ) и правильных библиотек ( google-guava ) не только упростит код, но и сделает его эффективный .

Код

public class BasicFrequencyCalculator
{
    public static void main(final String[] args) throws IOException
    {
        @SuppressWarnings("unchecked")
        Multiset<Word> frequency = Files.readLines(new File("c:/2.txt"), Charsets.ISO_8859_1, new LineProcessor() {

            private final Multiset<Word> result = HashMultiset.create();

            @Override
            public Object getResult()
            {
                return result;
            }

            @Override
            public boolean processLine(final String line) throws IOException
            {
                result.add(new Word(line));
                return true;
            }
        });
        for (Word w : frequency.elementSet())
        {
            System.out.println(w.getOriginal() + " = " + frequency.count(w));
        }
    }
}


public class Word
{
    private final String key;

    private final String original;

    public Word(final String orig)
    {
        this.original = orig.trim();
        String[] temp = original.toLowerCase().split("-");
        Arrays.sort(temp);
        key = temp[0] + "-"+temp[1];
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getKey() == null) ? 0 : getKey().hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj == null)
        {
            return false;
        }
        if (!(obj instanceof Word))
        {
            return false;
        }
        Word other = (Word) obj;
        if (getKey() == null)
        {
            if (other.getKey() != null)
            {
                return false;
            }
        }
        else if (!getKey().equals(other.getKey()))
        {
            return false;
        }
        return true;
    }

    @Override
    public String toString()
    {
        return getOriginal();
    }

    public String getKey()
    {
        return key;
    }

    public String getOriginal()
    {
        return original;
    }
}

Выход

BRAIN-TOLERATE     = 3
ISCHEMIA-GLUTAMATE = 3
GLUTAMATE-BRAIN    = 1
ISCHEMIA-BRAIN     = 1
0 голосов
/ 06 января 2011

Спасибо всем за вашу помощь.Вот как я это решил -

// Mapping of String->Integer (word -> frequency) 
    TreeMap<String, Integer> frequencyMap = new TreeMap<String, Integer>(); 

    // Iterate through each line of the file 
    String[] temp;
    String currentLine; 
    String currentLine2;
    while ((currentLine = in.readLine()) != null) { 

    temp=currentLine.split("-");
    currentLine2=temp[1]+"-"+temp[0];

    // Iterate through each word of the current line  
    StringTokenizer parser = new StringTokenizer(currentLine);
    while (parser.hasMoreTokens()) { 
    String currentWord = parser.nextToken(); 

    Integer frequency = frequencyMap.get(currentWord);  
    Integer frequency2 = frequencyMap.get(currentLine2);

    // Add the word if it doesn't already exist, otherwise increment the 
    // frequency counter. 
    if (frequency == null) {
        if (frequency2 == null)
            frequency = 0;
        else {
            frequencyMap.put(currentLine2, frequency2 + 1);
            break;
        }//else
    } //if (frequency == null)

    frequencyMap.put(currentWord, frequency + 1);
    }//while (parser.hasMoreTokens())

    }//while ((currentLine = in.readLine()) != null)

    // Display our nice little Map 
    System.out.println(frequencyMap);
...