Как посчитать частоту символов в строке? - PullRequest
25 голосов
/ 16 июля 2011

Мне нужно написать какой-то цикл, который может считать частоту каждой буквы в строке.
Например: «aasjjikkk» будет считать 2 «a», 1 «s», 2 «j», 1 «i», 3 «k».В конечном счете, идентифицируем, как они, чтобы в конечном итоге на карте с символом в качестве ключа и счетчиком в качестве значения.Любая хорошая идея, как это сделать?

Ответы [ 23 ]

31 голосов
/ 16 июля 2011

Вы можете использовать Java-карту и сопоставить char с int.Затем вы можете перебрать символы в строке и проверить, были ли они добавлены на карту, если они есть, вы можете затем увеличить его значение.

Например:

HashMap<Character, Integer> map = new HashMap<Character, Integer>();
String s = "aasjjikkk";
for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    Integer val = map.get(c);
    if (val != null) {
        map.put(c, new Integer(val + 1));
    }
    else {
       map.put(c, 1);
   }
}

В конце у вас будет количество всех персонажей, с которыми вы столкнулись, и вы можете извлечь из них их частоты.

В качестве альтернативы, вы можете использовать решение Bozho по использованию Multiset и подсчета общего числа случаев.

15 голосов
/ 16 июля 2011

Вы можете использовать Multiset (из guava ).Это даст вам счет для каждого объекта.Например:

Multiset<Character> chars = HashMultiset.create();
for (int i = 0; i < string.length(); i++) {
    chars.add(string.charAt(i));
}

Затем для каждого символа вы можете позвонить chars.count('a'), и он возвращает количество вхождений

9 голосов
/ 16 июня 2017

Краткий способ сделать это:

Map<Character,Integer> frequencies = new HashMap<>();
for (char ch : input.toCharArray()) 
   frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);

Мы используем for-each для циклического прохождения каждого символа. frequencies.getOrDefault() получает значение, если ключ присутствует, или возвращает (по умолчанию) свой второй аргумент.

6 голосов
/ 21 июля 2018

Использование потокового API с JDK-8:

Map<Character, Long> frequency =
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

или если вы хотите, чтобы ключи были целыми числами:

Map<Character, Integer> frequency =
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(c -> 1)));

Другой вариант:

Map<Character, Integer> frequency = 
            str.chars()
               .mapToObj(c -> (char)c)
               .collect(Collectors.toMap(Function.identity(), c -> 1, Math::addExact));
4 голосов
/ 12 сентября 2012

Вот еще одно решение, каким бы хитрым оно ни было.

public char getNumChar(String s) {
    char[] c = s.toCharArray();
    String alphabet = "abcdefghijklmnopqrstuvwxyz";
    int[] countArray = new int[26];
    for (char x : c) {
        for (int i = 0; i < alphabet.length(); i++) {
            if (alphabet.charAt(i) == x) {
                countArray[i]++;
            }
        }
    }

    java.util.HashMap<Integer, Character> countList = new java.util.HashMap<Integer, Character>();

    for (int i = 0; i < 26; i++) {
        countList.put(countArray[i], alphabet.charAt(i));
    }
    java.util.Arrays.sort(countArray);
    int max = countArray[25];
    return countList.get(max);
}
3 голосов
/ 16 июля 2011

Ну, на ум приходят два способа, и это зависит от ваших предпочтений:

  1. Сортировка массива по символам.Затем подсчет каждого персонажа становится тривиальным.Но сначала вам нужно будет сделать копию массива.

  2. Создайте еще один целочисленный массив размером 26 (скажем, freq), а str - это массив символов.

    for(int i = 0; i < str.length; i ++)

    freq[str[i] - 'a'] ++; //Assuming all characters are in lower case

Таким образом, число 'a' будет сохранено на частоте [0], а число 'z' -будет на частоте [25]

2 голосов
/ 16 июля 2011

Вот решение:

Определите свой собственный Pair:

public class Pair
{
    private char letter;
    private int count;
    public Pair(char letter, int count)
    {
        this.letter = letter;
        this.count= count;
    }
    public char getLetter(){return key;}
    public int getCount(){return count;}
}

Тогда вы можете сделать:

public static Pair countCharFreq(String s)
{
    String temp = s;
    java.util.List<Pair> list = new java.util.ArrayList<Pair>();
    while(temp.length() != 0)
    {
        list.add(new Pair(temp.charAt(0), countOccurrences(temp, temp.charAt(0))));
        temp.replaceAll("[" + temp.charAt(0) +"]","");
    }
}

public static int countOccurrences(String s, char c)
{
    int count = 0;
    for(int i = 0; i < s.length(); i++)
    {
        if(s.charAt(i) == c) count++;
    }
    return count;
}
2 голосов
/ 13 октября 2017

Поскольку решения Java 8 не было, подумал о публикации. Кроме того, это решение намного аккуратнее, удобочитаемее и кратко, чем некоторые другие решения, упомянутые здесь.

String string = "aasjjikkk";

Map<Character, Long> characterFrequency = string.chars()  // creates an IntStream
    .mapToObj(c -> (char) c) // converts the IntStream to Stream<Character>
    .collect(Collectors.groupingBy(c -> c, Collectors.counting())); // creates a
                                                                    // Map<Character, Long> 
                                                                    // where the Long is
                                                                    // the frequency
1 голос
/ 23 июня 2017

Вы можете использовать CharAdapter и CharBag из Eclipse Collections и избегать бокса до Character и Integer.

CharBag bag = CharAdapter.adapt("aasjjikkk").toBag();

Assert.assertEquals(2, bag.occurrencesOf('a'));
Assert.assertEquals(1, bag.occurrencesOf('s'));
Assert.assertEquals(2, bag.occurrencesOf('j'));
Assert.assertEquals(1, bag.occurrencesOf('i'));
Assert.assertEquals(3, bag.occurrencesOf('k'));

Примечание.коммиттер для коллекций Eclipse.

1 голос
/ 29 апреля 2019
String s = "aaaabbbbcccddddd";
Map<Character, Integer> map = new HashMap<>();

Использование одной строки в Java8

s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...