Liczenie krotności znaków w tekście.

0

Czy jest jakiś elegancki sposób (w stylu Javy 8) utworzenia HashMap<Character,Integer>, który przy liczeniu nie zwraca uwagi na wielkość liter, ale dopisując parę (klucz, wartość) bierze pod uwagę wielkość pierwszego wystąpienia litery?

"Ala jest wesoła." => ("A",3)
"Czy ktoś widział Alę?" =>("a",2)
0

Lepiej przed zliczaniem zrobić z wszystkich znaków małe litery i wtedy będzie wszystko jedno. Prościej.

0

Ale ja potrzebuję tak jak napisałem.
Twój pomysł prowadzi do dość dziwacznych wyników:

"ONZ, NATO, UE" => ("o",2),("n",2),...
0

Możesz stworzyć zmienną w której zapiszesz to czy pierwsza szukana litera jest mała czy duża potem sprowadzasz wszystko do małych liter po zliczeniu wszystkich liter robisz odczyt z tej zmiennej i zapisujesz to do Mapy.

0

Chyba tyle zmiennych ile jest znaków. Ja szukam eleganckiego kodu korzystającego ze strumieni (Java 8), by zapobiec niepasującym propozycjom podam kod, który mam (zmienna `letter' zawiera ostatni odczytany znak).

if(counters.containsKey(Character.toLowerCase(letter))){
      counters.put(Character.toLowerCase(letter),counters.get(Character.toLowerCase(letter)) + 1);
}
else if(counters.containsKey(Character.toUpperCase(letter))){
      counters.put(Character.toUpperCase(letter),counters.get(Character.toUpperCase(letter)) + 1);
}
else{
     counters.put(letter,1);
}
0

Mapa z obiektem trzymającym inta i boola oznaczającego wielkość?

1

Napisałem coś takiego mam nadzieję że o coś podobnego ci chodziło i że pomogłem.

String s = "Ala ma kota";
		List<Character> chars = new ArrayList<Character>();
		for(char c: s.toCharArray())
			chars.add(c);
		List<Character> Characters = new ArrayList<Character>();
		Map<Character, Integer> counts = chars.stream()
				.collect(Collectors.toConcurrentMap(
						new Function<Character, Character>()
						{
							@Override
							public Character apply(Character t) {
								if(Characters.contains(t.toString().toLowerCase().toCharArray()[0]))
									return t.toString().toLowerCase().toCharArray()[0];
								if(Characters.contains(t.toString().toUpperCase().toCharArray()[0]))
									return t.toString().toUpperCase().toCharArray()[0];
								Characters.add(t);
								return t;
							}
						}, w -> 1, Integer::sum));
		System.out.println(counts);
0

Dzięki, o to chodziło. Niestety kod nie jest dużo bardziej elegancki od kodu oldschoolowego (Java 7).

for(char letter: line.toCharArray()){
    if(counters.containsKey(Character.toLowerCase(letter))){
        counters.put(Character.toLowerCase(letter),counters.get(Character.toLowerCase(letter)) + 1);
    }
    else if(counters.containsKey(Character.toUpperCase(letter))){
       counters.put(Character.toUpperCase(letter),counters.get(Character.toUpperCase(letter)) + 1);
    }
    else{
       counters.put(letter,1);
    }
}
0
bogdans napisał(a):

Dzięki, o to chodziło. Niestety kod nie jest dużo bardziej elegancki od kodu oldschoolowego (Java 7).

for(char letter: line.toCharArray()){
    if(counters.containsKey(Character.toLowerCase(letter))){
        counters.put(Character.toLowerCase(letter),counters.get(Character.toLowerCase(letter)) + 1);
    }
    else if(counters.containsKey(Character.toUpperCase(letter))){
       counters.put(Character.toUpperCase(letter),counters.get(Character.toUpperCase(letter)) + 1);
    }
    else{
       counters.put(letter,1);
    }
}

Też tak myślę.

0

Dodatkowo z taką implementacją jaką pokazał @Th0ru5 jest jeszcze jeden problem. Collector toConcurrentMap ma zdefiniowaną charakterystykę m.in. jako Characteristics.UNORDERED a to oznacza, że początkowy string może zostać analizowany niekoniecznie w takiej kolejności w jakiej się tego spodziewa @bogdans Wydaje mi się, że w tym przypadku jedyna prawidłowa charakterystyka to Characteristics.IDENTITY_FINISH

0

a coś takiego?

	@Test
	public void shouldWork() {
		// given
		String input = "Ahewadssada";
		Character letter = 'a';
		HashMap<Character, Integer> returnedMap = new HashMap<>();
		HashMap<Character, Integer> expectedMap = new HashMap<>();
		expectedMap.put('A', 4);
		// when
		String returned = input.chars().filter(e -> Character.toLowerCase(e) == letter).collect(StringBuilder::new,   StringBuilder::appendCodePoint, StringBuilder::append).toString();
		returnedMap.put(returned.charAt(0), returned.length());
		// then
		assertThat(returnedMap).isEqualTo(expectedMap);
	}

de facto wszystko sprowadza się do 3 linijek:

HashMap<Character, Integer> returnedMap = new HashMap<>();
String returned = input.chars().filter(e -> Character.toLowerCase(e) == letter).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
		returnedMap.put(returned.charAt(0), returned.length());

1 użytkowników online, w tym zalogowanych: 0, gości: 1