Сортировать список строк по символам в Java - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь написать программу для упорядочения списка строк по наименее часто встречающимся символам в списке. Например, если бы список был [apple, orange, banana], частота букв в списке была бы a - 5, n - 3, p - 2, e - 2, l - 1, o - 1, r - 1, g - 1, b - 1. Так как оранжевый содержит наименее часто встречающиеся буквы, программа возвращает оранжевый, затем яблоко, затем банан.

До сих пор я написал код, который упорядочивает все буквы в списке по частоте. Но мне нужно применить это, чтобы найти, какая строка содержит наименее часто встречающиеся буквы.

Вот мой код:

    Map<Character, Integer> elemCount = new LinkedHashMap<>();
    for (String word : words)
    {
        for (int i = 0; i  < word.length(); i++)
        {
            if (elemCount.containsKey(word.charAt(i)))
            {
                elemCount.put(word.charAt(i), elemCount.get(word.charAt(i)) + 1);
            }
            else
            {
                elemCount.put(word.charAt(i), 1);
            }
        }
    }
    ArrayList<Character> sortedElems = new ArrayList<>();
    elemCount.entrySet().stream().sorted(Collections.reverseOrder
    (Map.Entry.comparingByValue())).forEach(entry -> 
    { 
        for (int i = 1; i <= entry.getValue(); i++)
        {
            sortedElems.add(entry.getKey());
        }
    }
    );
    System.out.println(sortedElems);

Ответы [ 4 ]

5 голосов
/ 05 апреля 2020

попробуйте следующий код:

public static void main(String[] args){
        List<String> list = new ArrayList<String>();
        list.add("apple");
        list.add("banana");
        list.add("orange");
        System.out.println(leastFrequentString(list));

    }


    private static Set<String> leastFrequentString(List<String> list){
        Map<String, Integer> mapStringToFrequency = new HashMap<>();
        for(String s:list){
            Map<Character, Integer> mapCharacterToFrequency =  wordFrequency(s);
            int totalScore = 0;
            for(Character c:mapCharacterToFrequency.keySet()){
                if(mapCharacterToFrequency.get(c)>1){
                    totalScore+=1;
                }
            }
            mapStringToFrequency.put(s,totalScore);
        }
        HashMap sortByValue =  sortByValue(mapStringToFrequency);
        return sortByValue.keySet();
    }

    private static Map<Character,Integer> wordFrequency(String s){
        Map<Character, Integer> mapCharacterToFrequency = new HashMap<Character, Integer>();
        for(Character c: s.toCharArray()){
            if(mapCharacterToFrequency.containsKey(c)){
                int frequency = mapCharacterToFrequency.get(c);
                frequency +=1;
                mapCharacterToFrequency.replace(c,frequency);
            }else{
                mapCharacterToFrequency.put(c,1);
            }
        }
        return mapCharacterToFrequency;
    }

    private static LinkedHashMap<String, Integer> sortByValue(Map<String, Integer> hm)
    {
        // Create a list from elements of HashMap
        List<Map.Entry<String, Integer> > list =
                new LinkedList<>(hm.entrySet());

        // Sort the list
        list.sort(Comparator.comparing(Map.Entry::getValue));

        // put data from sorted list to HashMap
        LinkedHashMap<String, Integer> temp = new LinkedHashMap<>();
        for (Map.Entry<String, Integer> aa : list) {
            temp.put(aa.getKey(), aa.getValue());
        }
        return temp;
    }
2 голосов
/ 05 апреля 2020
public class Main {
    public List<String> sortAccordingly(List<String> unsortedList ) {
        List<String> sorted=new ArrayList<>();

        Map<String,Integer> freq=new TreeMap();
        for(String s:unsortedList) {
            Map<Character, Integer> fq = new HashMap<>();
            for (int i = 0; i < s.length(); i++) {
                if (fq.containsKey(s.charAt(i)))
                    fq.replace(s.charAt(i), fq.get(s.charAt(i)) + 1);
                else
                    fq.put(s.charAt(i), 1);
            }
            freq.put(s, Collections.max(fq.values()));
        }
        Map<String,Integer> sortedOne=freq.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e1,LinkedHashMap::new));
        sortedOne.putAll(freq);
        sorted.addAll(sortedOne.keySet());
        return sorted;

    }


    public static void main(String[] args) {
        List <String> list=new ArrayList<>();
        list.add("apple");
        list.add("orange");
        list.add("banana");
        System.out.println(new Main().sortAccordingly(list));

    }
}

Вы можете использовать компаратор

Comparator<String> valueCompare=new Comparator<String>() {
            @Override
            public int compare(String s, String t1) {
                return freq.get(s).compareTo(freq.get(t1));
            }
        };

вместо

Map<String,Integer> sortedOne=freq.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e1,LinkedHashMap::new));

после того, как эта функция будет

public List<String> sortAccordingly(List<String> unsortedList ) {
        List<String> sorted=new ArrayList<>();

        Map<String,Integer> freq=new TreeMap();
        Comparator<String> valueCompare=new Comparator<String>() {
            @Override
            public int compare(String s, String t1) {
                return freq.get(s).compareTo(freq.get(t1));
            }
        };
        for(String s:unsortedList) {
            Map<Character, Integer> fq = new HashMap<>();
            for (int i = 0; i < s.length(); i++) {
                if (fq.containsKey(s.charAt(i)))
                    fq.replace(s.charAt(i), fq.get(s.charAt(i)) + 1);
                else
                    fq.put(s.charAt(i), 1);
            }
            freq.put(s, Collections.max(fq.values()));
        }
        Map<String,Integer> sortedOne=new TreeMap<>(valueCompare);
        sortedOne.putAll(freq);
        sorted.addAll(sortedOne.keySet());
        return sorted;

    }
1 голос
/ 05 апреля 2020

Вы можете разделить решение на следующие шаги:

  • Найдите наименее часто встречающиеся буквы. В вашем примере с фруктами это буквы l, o, r, g и b - все имеют частоту 1.
  • Подсчитайте, сколько из этих букв содержится в каждом слове: у яблока 1, у апельсина 3, банан имеет 1
  • Сортировка слов по этому количеству

Именно так вы можете найти наименее часто встречающиеся буквы. Сначала найдите самую низкую частоту, повторяя карту elemCount. Затем повторите итерацию по карте, чтобы найти буквы с наименьшей частотой:

        int lowestFrequency = ...result from
        List<Character> leastFrequentLetters = new ArrayList<>();
        for (Map.Entry<Character, Integer> entry : elemCount.entrySet()) {
            if (entry.getValue() == lowestFrequency) {
                leastFrequentLetters.add(entry.getKey());
            }
        }

Вот как вы можете посчитать, сколько букв данного слова в наименьшем количестве повторяются:

        int count = 0;
        for (char c: word.toCharArray()) {
            if (leastFrequentLetters.contains(c)) {
                count = count + 1;
            }
        }

Если у вас есть метод для получения или вычисления этого количества для каждого слова, вы можете отсортировать слова по нему. Имеет смысл?

0 голосов
/ 05 апреля 2020

Если у вас есть список, как вы предложили: [яблоко, апельсин, банан] с частотой букв a - 5, n - 3, p - 2, e - 2, l - 1, o - 1, r - 1, g - 1, b - 1

Как я вижу, вы уже написали код для получения этих частот

Следующим шагом является:

итерация по элементам списка - > сумма частот каждой буквы для яблока, апельсина и банана -> сортировка! так что вы можете получить их в правильном порядке.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...