Ler frequência de palavras

8 respostas
Ziguifrid

Tenho esse algorítimo que lê um determinado texto e mostra quantas vezes a palavra aparece.

O problema:

No [color=red]System.out.println("texto = '" + keyString + "' contagem = '" + valueString + "'");[/color] o resultado é obtido.

Mas quando peço para aparecer o resultado em [color=darkred]jTextArea2.setText("texto = '" + keyString + "' contagem = '" + valueString + "'");
[/color] só aparece a contagem da última palavra do texto, por que será?

Outra coisa:

Tem como ordenar os resultado?

Como aparecer a palavra com maior frequência primeiro e ir decrescendo.

Como neste site aqui.

http://rainbow.arch.scriptmania.com/tools/word_counter.html

import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
        HashMap<String, Integer> lista = new HashMap<String, Integer>();

		//String texto = "minha";

        jTextArea1.getText();
		StringTokenizer st = new StringTokenizer(jTextArea1.getText());

	     while (st.hasMoreTokens()) {
	    	String token = st.nextToken();
			if(lista.get(token) != null) {
				Integer total = lista.get(token);
				lista.put(token, total = total+1);
			} else {
				lista.put(token, 1);
			}
	     }
	     for (Iterator iter = lista.keySet().iterator(); iter.hasNext();) {
				String keyString = (String) iter.next();
				Integer valueString = lista.get(keyString);
				System.out.println("texto = '" + keyString + "' contagem = '" + valueString + "'");

                                 jTextArea2.setText("texto = '" + keyString + "' contagem = '" + valueString + "'");

	     }
	
    }

8 Respostas

M

faca o seguinte na hora se setar o textArea…

jTextArea2.setText(jTextArea2.getText() + "\n" + "texto = '" + keyString + "' contagem = '" + valueString + "'");

flw…

Ziguifrid

Valeu MuCReis

Agora só resta ver se alguém sabe um jeito de ordenar as palavras com maior frequência de aparição para a menor.

Alexandre_Saudate

Aí está. O código está BEM mal escrito, então, favor arrumar :wink:

String texto = "texto palavra texto palavra texto";
		
		
		class ComparadorFrequencia<T> implements Comparable<ComparadorFrequencia<T>> {
			T objeto;
			int frequencia = 0;
				
			@Override
			public int compareTo(ComparadorFrequencia o) {				
				return o.frequencia - this.frequencia;
			}
			
			public ComparadorFrequencia(T objeto) {
				this.objeto = objeto;
			}
			
			public boolean equals (Object o) {
				if (!(o instanceof ComparadorFrequencia))
					return false;
				ComparadorFrequencia<T> aquele = (ComparadorFrequencia<T>)o;
				return this.objeto.equals(aquele.objeto);
			}
		} 
		
		StringTokenizer tokenizer = new StringTokenizer(texto);
		List<ComparadorFrequencia<String>> lista = new ArrayList<ComparadorFrequencia<String>>();
		List<String> palavras = new ArrayList<String>();
		
		while (tokenizer.hasMoreTokens()) {
			palavras.add(tokenizer.nextToken());
		}
		Collections.sort(palavras);
		
		for (String palavra : palavras) {
			int index = lista.indexOf(new ComparadorFrequencia<String>(palavra));
			if (index != -1) {
				ComparadorFrequencia<String> comparador = lista.get(index);
				comparador.frequencia++;
			}
			
			else  {
				ComparadorFrequencia<String> comparador = new ComparadorFrequencia<String>(palavra);
				comparador.frequencia++;
				lista.add(comparador);
			}
		}
		
		Collections.sort(lista);
		for (ComparadorFrequencia<String> comparador : lista) {
			System.out.println("Palavra: " + comparador.objeto + " frequencia: " + comparador.frequencia);
		}
Ziguifrid

Só o que eu quero é ordenar as palavras que aparecem com mais frequência em um texto, e não ordená-las em ordem alfabética.

Estou fazendo assim:

Só que este código só esta ordenando os valores e não mostra de qual palavra este valor corresponde e este é o problema.

import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

SortedHashMap<String, Integer> map = new SortedHashMap<String, Integer>();

HashMap<String, Integer> lista = new HashMap<String, Integer>();
   String keyString;
     Integer valueString;

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
    

        jTextArea1.getText();
		StringTokenizer st = new StringTokenizer(jTextArea1.getText());

	     while (st.hasMoreTokens()) {
	    	String token = st.nextToken();
			if(lista.get(token) != null) {
				Integer total = lista.get(token);
				lista.put(token, total = total+1);
                                 
			} else {
				lista.put(token, 1);
			}
	     }
	     for (Iterator iter = lista.keySet().iterator(); iter.hasNext();) {
				 keyString = (String) iter.next();
				 valueString = lista.get(keyString);

      jTextArea2.setText(jTextArea2.getText() + "\n" + "texto = '" + keyString + "' contagem = '" + valueString + "'");
       jTextArea3.setText(jTextArea3.getText() +"\n" + valueString);

 map.put(new String(keyString), new Integer(valueString));


     }
  
	
    }                                        

   

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        

 Iterator iter = map.iterator();
   

 while (iter.hasNext()) {
  System.out.println(iter.next()); 

 }


    }
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

/**
 *
 * @author Michel A. Medeiros
 */
public class SortedHashMap  <E, T> extends HashMap<E, T> {
    public Iterator<Object> iterator() {
        Collection<T> collection = this.values();
        Object[] array = collection.toArray();
        Arrays.sort(array);
         return Arrays.asList(array).iterator();
     }  
}
M

Use os seguintes métodos:

private Map<String, Integer> mapa;                                                            
                                                                                              
private void resgataEOrdenaLista(String palavras) {                                           
	// garante ordem alfabética por padrão                                                    
	mapa = new TreeMap<String, Integer>();                                                    
	// cria um Scanner para ler                                                               
	Scanner scanner = new Scanner(palavras);                                                  
	// enquanto houver mais palavras                                                          
	while (scanner.hasNext()) {                                                               
		// pega a próxima palavra                                                             
		String palavra = scanner.next();                                                      
		// verifica se ela já existe no mapa                                                  
		Integer freq = mapa.get(palavra);                                                     
		// e adiciona-a com a nova frequência (1, se ela ainda não existia                    
		// ou incrementa 1 na frequência anterior, caso existisse)                            
		mapa.put(palavra, freq == null ? 1 : freq + 1);                                       
	}                                                                                         
}                                                                                             
                                                                                              
private void adicionaMapaAoTextArea(JTextArea textArea,                                       
		Set<Entry<String, Integer>> set) {                                                    
	// para cada entrada do mapa, adiciona uma linha ao final                                 
	for (Entry<String, Integer> e : set) {                                                    
		textArea.append("texto = '" + e.getKey());                                            
		textArea.append("', contagem = " + e.getValue());                                     
		textArea.append("\n");                                                                
	}                                                                                         
}                                                                                             
                                                                                              
private Set<Entry<String, Integer>> ordenaPorQuantidades() {                                  
	// o Comparator responsável por ordenar nosso Set de Entry                                
	Comparator<Entry<String, Integer>> comparator = new Comparator<Entry<String, Integer>>() {
                                                                                              
		@Override                                                                             
		public int compare(Entry<String, Integer> o1,                                         
				Entry<String, Integer> o2) {                                                  
			// se a contagem, retorna a comparação por Strings                                
			if (o1.getValue() == o2.getValue()) {                                             
				return o1.getKey().compareTo(o2.getKey());                                    
			}                                                                                 
			// senão, retorna por contagem mesmo                                              
			return o1.getValue().compareTo(o2.getValue());                                    
			// se quiser em ordem decrescente comente a linha acima e                         
			// decomente a linha abaixo:                                                      
			// return o2.getValue().compareTo(o1.getValue());                                 
		}                                                                                     
                                                                                              
	};                                                                                        
	// cria um Set ordenado pelo Compartator acima                                            
	Set<Entry<String, Integer>> entries = new TreeSet<Entry<String, Integer>>(                
			comparator);                                                                      
	// e adiciona o conteúdo do mapa                                                          
	entries.addAll(mapa.entrySet());                                                          
	return entries;                                                                           
}

Você o usará da seguinte forma:

// para pegar em ordem alfabética
resgataEOrdenaLista(jTextArea1.getText());
// se quiser nessa ordem mesmo, faça assim:
adicionaMapaAoTextArea(jTextArea2, mapa.entrySet());
// se quiser em ordem de aparição, use:
adicionaMapaAoTextArea(jTextArea2, ordenaPorQuantidades());

Note que, apesar da ordenação funcionar ele não é feita no mapa, e sim em uma cópia de seus valores (obtida por entrySet). Isso porque não percebi nenhuma maneira melhor de se fazer (talvez outra pessoa possa ajudar).

ViniGodoy

Só fique atento à alguns detalhes no código do Marco, que representam boas práticas hoje em dia:

a) Use o Scanner ou o método split no lugar do StringTokenizer. Diz o JavaDoc do StringTokenizer, no Java 5 em diante:

b) Use o for each no lugar do Iterator.
http://java.sun.com/j2se/1.5.0/docs/guide/language/foreach.html

c) Use o método Append do JTextArea. Se for concatenar strings num for, antes de incluir no JTextArea, use um StringBuilder.

Por fim, se esse processamento for de um texto muito longo, você poderá experimentar uma interface gráfica congelada. Nesse caso, você terá que deslocar o processamento para uma segunta thread, liberando a thread do swing para fazer pintura. A respeito desse assunto, leia o tutorial:
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

M

ViniGodoy:
Por fim, se esse processamento for de um texto muito longo, você poderá experimentar uma interface gráfica congelada. Nesse caso, você terá que deslocar o processamento para uma segunta thread, liberando a thread do swing para fazer pintura. A respeito desse assunto, leia o tutorial:
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

Muito bem lembrado. Talvez isso deve rodar em uma Thread separada (pode-se usar SwingWorker para abstrair isso).

Alexandre_Saudate

Ziguifrid:
Só o que eu quero é ordenar as palavras que aparecem com mais frequência em um texto, e não ordená-las em ordem alfabética.

Se você for reparar, verá que o código que te passei, com aquela classe que implementa Comparable, está comparando pela frequencia, não pela ordem. Então, a lista que contém estas classes ordena, sim, pela ordem de frequencia.

Criado 3 de janeiro de 2010
Ultima resposta 4 de jan. de 2010
Respostas 8
Participantes 5