【问题标题】:Sort List of Strings by Characters In JavaJava中按字符排序字符串列表
【发布时间】:2020-07-17 10:05:52
【问题描述】:

我正在尝试编写一个程序来按列表中最不常见的字符对字符串列表进行排序。例如,如果列表为[apple, orange, banana],则列表中的字母频率将为 a - 5、n - 3、p - 2、e - 2、l- 1、o - 1、r - 1、g - 1、 b - 1. 由于 orange 包含最不常见的字母,因此程序将返回 orange,然后是 apple,然后是 banana。

到目前为止,我已经编写了按频率对列表中所有字母进行排序的代码。但我需要应用它来查找哪个字符串包含最不常见的字母。

这是我的代码:

    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);

【问题讨论】:

  • “最不频繁”是什么意思?频率最低的单词中有多少个字母?字母频率总和?
  • 出现频率最低的单词中的字母个数

标签: java string sorting collections


【解决方案1】:

如果您有您建议的列表: [苹果、橙子、香蕉]有字母频率 a - 5, n - 3, p - 2, e - 2, l- 1, o - 1, r - 1, g - 1, b - 1

如我所见,您已经编写了获取这些频率的代码

下一步是:

遍历列表元素 -> 苹果、橙子和香蕉每个字母的频率总和 -> 排序!这样您就可以按正确的顺序获取它们。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以将解决方案分为以下步骤:

    • 查找频率最低的字母。在您的水果示例中,这些字母是 l、o、r、g 和 b - 频率均为 1。
    • 计算每个单词中包含多少个这些字母:apple 有 1 个,orange 有 3 个,banana 有 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;
                }
            }
    

    一旦您有一种方法可以检索或计算每个单词的计数,您就可以按它对单词进行排序。有意义吗?

    【讨论】:

    • 你是如何得到变量词的?
    • 您可以遍历列表words,或者您可以创建一个单独的方法来进行计数,您可以在words.sort(Comparator.comparing(word -&gt; { ... }) 样式的lambda 表达式中排序......这么多选项
    • 一旦我有了计数,我如何保存哪个单词包含什么计数以及我如何对其进行排序?
    • 您可以创建一个Map 数据结构,就像您有一个用于字母频率的数据结构一样。如果您在名为countLetters 的变量中有这样的映射,则可以使用words.sort(Comparator.comparing(word -&gt; countLetters.get(word)) 进行排序
    【解决方案3】:

    试试下面的代码:

    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;
        }
    

    【讨论】:

    • 打印出来的是一个单词而不是一个列表
    • 另外,这段代码是否显示了出现频率最高的单词?
    • 我只是想告诉你如何打印最少的一个。现在检查...
    • @NikeDog 如果这对您有用,请接受答案。
    【解决方案4】:
    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;
    
        }
    

    【讨论】:

    • 运行时,我没有得到按频率排序的列表。
    猜你喜欢
    • 1970-01-01
    • 2013-04-19
    • 2021-06-10
    • 2016-01-29
    • 2017-08-11
    • 2013-06-08
    • 1970-01-01
    • 2018-07-02
    • 2017-07-23
    相关资源
    最近更新 更多