Gå til innhold

Finne antall unike ord(Strings?) i ArrayList


Anbefalte innlegg

Hei!

 

Har et problem jeg har slitt med i dagevis nå som begynner å bli forferdelig irriterende.

 

Jeg har lest inn en bok (med et ord per linje) og lagt den inn i en ArrayList. Det har jeg fått til. Jeg har også fått til å telle antall forekomster av et gitt ord.

 

Det jeg nå sliter med er å finne hvor mange unike ord som forekommer i teksten, eller altså antall unike Strings som forekommer i ArrayListen min.

 

Jeg føler jeg har prøvd alt, jeg har søkt rundt omkring på nettet... men jeg kommer ingen vei. Jeg ser mange anbefaler HashMap eller hva det nå heter, men jeg er egentlig ute etter å gjøre det med en enkel loop om det lar seg gjøre.

 

Håper på god hjelp.

 

På forhånd takk!

Lenke til kommentar
Videoannonse
Annonse

Det lar seg gjøre. Den enkle (ikke nødvendigvis mest effektive) men enkle løsningen jeg ville gjort er å bare loope igjenom ArrayListen din, inne i loopen Så kan du lage ett hashmap, http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html Key'en i haspmap'et vil være ordet og value vil være antall gang det er funnet, hvis du ikke finner ordet ditt i hashmap'en. Legg det til med en verdi på 1, finner du det i hashmap'en, trekk ut verdien basert på din key, øk den med en og sett inn den nye verdien i hashmap'et.

 

Ps: Hvis du skal bruke beregningene senere, så kanskje du burde legge hashmap'en utenfor loopen.

 

Her er ett ganske enkelt forslag til det du spør etter, håper dette hjelper deg litt lengre.

import java.util.ArrayList;
import java.util.HashMap;

public class wordCount {
	public static void main(String args[]) {
		ArrayList<String> someWords = new ArrayList<String>();
		HashMap<String, Integer> countWords = new HashMap<String, Integer>();
		
		// Legger bare til noen ord i ArrayListen
		someWords.add("bok");
		someWords.add("bok");
		someWords.add("hest");
		someWords.add("bolle");
		
		// Vi leter igjennom vår arraylist	
		for (String s : someWords) {
			// Vi sjekker vår hashmap, om den inneholder vårt ord.
			if (countWords.containsKey(s)) {
			int wordCount;
			// Vi teller antall ganger ordet har blitt funnet
			wordCount = (countWords.get(s) + 1);
			// og legger den nye verdien til hashmap'en
			countWords.put(s, wordCount);
			// Jeg har bare tatt en utskrift
			System.out.println("Vi har funnet: "+s+" Den er funnet " + countWords.get(s) + " ganger");
			} 
			// Vi fant ikke ordet og legger det da til hashmap'en
			else { 
					countWords.put(s, 1);
			}
		}
	}
}
Endret av Lock-Aze
Lenke til kommentar

Er dette INF1000 oblig? Når du har laget en en array som inneholder alle ord, de er lagt inn sekvensielt og resten er tomme felter, kan du lage en loop som sjekker om det finnes et ord i første slot. Gjør det det, legg til +1 på counter og kjør loop igjen for å sjekke felt nummer 2, etc..

 

Bruk while (array !=null) for å sjekke om feltet har et ord eller ikke. Når den finner første felt med null-verdi, som betyr at det er slutt med ord i array, slutter loopen. Og counter-verdien er så mange unike ord den fant før den gikk tom for ord.

 

Om jeg forstår deg rett, kan det funke?

 

Edit:

Og om ikke det er unike ord i din array (alle lagt inn sekvensielt, om det finnes fra før eller ikke) kan du først kopiere unike ord over i nytt array2:

 

Les ord fra array. Sjekk om det finnes i array2 (while loop). Om ikke, kopier inn på neste ledige plass i array2 (bruk counter som array id). Da vil array2 bestå av de unike ordene, og de vil kun stå der en gang, uavhengig av om de forekommer flere ganger i teksten.

 

Og da kan du telle dem som beskrevet over. Kanskje ikke superelegant, men enkelt.

Endret av wanawanga
Lenke til kommentar

Er dette INF1000 oblig? Når du har laget en en array som inneholder alle ord, de er lagt inn sekvensielt og resten er tomme felter, kan du lage en loop som sjekker om det finnes et ord i første slot. Gjør det det, legg til +1 på counter og kjør loop igjen for å sjekke felt nummer 2, etc..

 

Bruk while (array !=null) for å sjekke om feltet har et ord eller ikke. Når den finner første felt med null-verdi, som betyr at det er slutt med ord i array, slutter loopen. Og counter-verdien er så mange unike ord den fant før den gikk tom for ord.

 

Om jeg forstår deg rett, kan det funke?

 

Edit:

Og om ikke det er unike ord i din array (alle lagt inn sekvensielt, om det finnes fra før eller ikke) kan du først kopiere unike ord over i nytt array2:

 

Les ord fra array. Sjekk om det finnes i array2 (while loop). Om ikke, kopier inn på neste ledige plass i array2 (bruk counter som array id). Da vil array2 bestå av de unike ordene, og de vil kun stå der en gang, uavhengig av om de forekommer flere ganger i teksten.

 

Og da kan du telle dem som beskrevet over. Kanskje ikke superelegant, men enkelt.

 

Tjah, du kan jo også lage en klasse som heter ord (eller noe i den duren) for så å legge til en instans av ord i arraylisten, orklassen trenger to inputs, ordet og antalltilfeller, så kan du jo loope igjennom og legge til fra klassen til listen, en noe mer tungvint måte å gjøre det på enn å bruke hashmap i mine øyne, men det vil også virke. Man vil jo få to løkker uansett, en løkke for å lage ordlisten og en løkke for å hente ut det man ønsker.

 

Å bruke flere array for å hente ting frem og tilbake høres helt ufattelig tungvint ut, men skjønner hva du mener .. ;)

Endret av Lock-Aze
Lenke til kommentar

Her er et forsøk (har ikke testet koden):

public int countUniqueElements(List<String> list) {
  int result = 0;
  ArrayList<String> tmpList = new ArrayList<String>(list);
  while (tmpList.size() > 0) {
    result++;
    for (int i = tmpList.size()-1; i >= 0; i--) {
      if (tmpList.get(i).equals(tmpList.get(0)) {
        tmpList.remove(i);
      }
    }
  }
  return result;
}

(det finnes nok noe bedre å bruke en ArrayList i denne funksjonen, da elementer fjernes fra listen i "vilkårlig" rekkefølge - LinkedList vil f.eks. muligens være bedre)

 

Edit: Eller du kan bruke "contains()" som allerede ligger klar til bruk for alle "Collection"-objekter, slik:

public List<String> getUniqueElements(List<String> list) {
  ArrayList<String> uniqueList = new ArrayList<String>();
  for (String item : list)
    if (!uniqueList.contains(item)) uniqueList.add(item);
  return uniqueList;
}
...
int noOfUniqueElements = getUniqueElements(list).size();
Endret av jonny
Lenke til kommentar

 

Er dette INF1000 oblig? Når du har laget en en array som inneholder alle ord, de er lagt inn sekvensielt og resten er tomme felter, kan du lage en loop som sjekker om det finnes et ord i første slot. Gjør det det, legg til +1 på counter og kjør loop igjen for å sjekke felt nummer 2, etc..

 

Bruk while (array !=null) for å sjekke om feltet har et ord eller ikke. Når den finner første felt med null-verdi, som betyr at det er slutt med ord i array, slutter loopen. Og counter-verdien er så mange unike ord den fant før den gikk tom for ord.

 

Om jeg forstår deg rett, kan det funke?

 

Edit:

Og om ikke det er unike ord i din array (alle lagt inn sekvensielt, om det finnes fra før eller ikke) kan du først kopiere unike ord over i nytt array2:

 

Les ord fra array. Sjekk om det finnes i array2 (while loop). Om ikke, kopier inn på neste ledige plass i array2 (bruk counter som array id). Da vil array2 bestå av de unike ordene, og de vil kun stå der en gang, uavhengig av om de forekommer flere ganger i teksten.

 

Og da kan du telle dem som beskrevet over. Kanskje ikke superelegant, men enkelt.

 

Tjah, du kan jo også lage en klasse som heter ord (eller noe i den duren) for så å legge til en instans av ord i arraylisten, orklassen trenger to inputs, ordet og antalltilfeller, så kan du jo loope igjennom og legge til fra klassen til listen, en noe mer tungvint måte å gjøre det på enn å bruke hashmap i mine øyne, men det vil også virke. Man vil jo få to løkker uansett, en løkke for å lage ordlisten og en løkke for å hente ut det man ønsker.

 

Å bruke flere array for å hente ting frem og tilbake høres helt ufattelig tungvint ut, men skjønner hva du mener .. ;)

 

 

Ja, finnes nok bedre måter å gjøre det på, men kjenner igjen denne problemstillingen fra en skoleoppgave på UiO nå i høst som jeg jobber med selv. Og om det er til den, da kan det være greit å gjøre det med de verktøyene man har lært så langt, der man forstår tankegangen og forstå hvorfor, istedet for å gå videre med verktøy man har mindre kontroll på som gjør jobben bedre...jeg forstår godt en motvilje mot å bruke et nytt verktøy som hashmap, dersom man ikke har vært borti det før, 3-4 dager før innlevering av oppgave :-)

Lenke til kommentar

 

 

Er dette INF1000 oblig? Når du har laget en en array som inneholder alle ord, de er lagt inn sekvensielt og resten er tomme felter, kan du lage en loop som sjekker om det finnes et ord i første slot. Gjør det det, legg til +1 på counter og kjør loop igjen for å sjekke felt nummer 2, etc..

 

Bruk while (array !=null) for å sjekke om feltet har et ord eller ikke. Når den finner første felt med null-verdi, som betyr at det er slutt med ord i array, slutter loopen. Og counter-verdien er så mange unike ord den fant før den gikk tom for ord.

 

Om jeg forstår deg rett, kan det funke?

 

Edit:

Og om ikke det er unike ord i din array (alle lagt inn sekvensielt, om det finnes fra før eller ikke) kan du først kopiere unike ord over i nytt array2:

 

Les ord fra array. Sjekk om det finnes i array2 (while loop). Om ikke, kopier inn på neste ledige plass i array2 (bruk counter som array id). Da vil array2 bestå av de unike ordene, og de vil kun stå der en gang, uavhengig av om de forekommer flere ganger i teksten.

 

Og da kan du telle dem som beskrevet over. Kanskje ikke superelegant, men enkelt.

 

Tjah, du kan jo også lage en klasse som heter ord (eller noe i den duren) for så å legge til en instans av ord i arraylisten, orklassen trenger to inputs, ordet og antalltilfeller, så kan du jo loope igjennom og legge til fra klassen til listen, en noe mer tungvint måte å gjøre det på enn å bruke hashmap i mine øyne, men det vil også virke. Man vil jo få to løkker uansett, en løkke for å lage ordlisten og en løkke for å hente ut det man ønsker.

 

Å bruke flere array for å hente ting frem og tilbake høres helt ufattelig tungvint ut, men skjønner hva du mener .. ;)

 

 

Ja, finnes nok bedre måter å gjøre det på, men kjenner igjen denne problemstillingen fra en skoleoppgave på UiO nå i høst som jeg jobber med selv. Og om det er til den, da kan det være greit å gjøre det med de verktøyene man har lært så langt, der man forstår tankegangen og forstå hvorfor, istedet for å gå videre med verktøy man har mindre kontroll på som gjør jobben bedre...jeg forstår godt en motvilje mot å bruke et nytt verktøy som hashmap, dersom man ikke har vært borti det før, 3-4 dager før innlevering av oppgave :-)

 

 

Har gjort lignende oppgaver (dog ikke i java) på skolen, fikk noe a-la dette i bash (vi skulle da finne unike ip'er og sortere ut hvor mange ganger hver ip hadde besøkt en side) brukte da associative array (som jeg synes er ganske likt en hashmap)

 

Vi har noen lærere som tildels har kicket mer på at man looper flere ganger enn man må, enn at man tar i bruk nye/andre funksjoner enn det som var tiltenkt oppgaven. (effektiv programmering etc.)

 

Men, hvis man får det til å fungere med 2-3 forskjellige array og looper igjennom disse, så kan det jo være en grei måte å komme igang på. Jeg har en del flere måter å gjøre det på, men noen av disse synes jeg ikke akkurat er enkle for noe som høres ut som førsteåret i java? (Jeg gjetter, siden du sier faget er INF1000)

 

Nå forstår jeg hvorfor hashmap kan synes noe tungvint i starten (mye grunnet jeg spurte en kompis om hjelp med en oppgave når jeg hadde mitt første møte med java og svaret hans var: Dette fikser du enkelt med hashmap og jeg syntes hele greia så mye mer komplisert ut enn det egentlig var)

Lenke til kommentar

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

Laster...
×
×
  • Opprett ny...