【问题标题】:How to sort a list of strings based on Character Frequency如何根据字符频率对字符串列表进行排序
【发布时间】:2021-12-20 18:06:33
【问题描述】:

我有一个字符串列表,我需要根据每个单词中 A 的频率对它们进行排序。如果 A 相等,则比较 B,依此类推,直到 Z。假设当然列表中没有字谜。

示例:[Banana, Isle, Best, Barb]

排序:[Banana, Barb, Best, Isle]

【问题讨论】:

  • 将每个单词转换为 char 数组,循环遍历数组并为数组中出现的每个“a”加 1。不过可能不是最有效的方法。
  • 欢迎。请阅读How to Ask 并使用tour

标签: java sorting


【解决方案1】:

初始数组中的单词可以使用比较器对从给定单词的排序字符数组构建的转换字符串进行排序:

public static String convert(String s) {
    char[] c = s.toLowerCase().toCharArray();
    Arrays.sort(c);
    return new String(c);
}
String[] data = {"Banana", "Isle", "Best", "Barb", "Abracadabra", "aardvark", "Barnabie"};
Arrays.sort(data, Comparator.comparing(MyClass::convert));
System.out.println(Arrays.toString(data));

输出:

[Abracadabra, Banana, aardvark, Barnabie, Barb, Best, Isle]

【讨论】:

    【解决方案2】:

    您正在对多个标准进行排序,26 个标准,看起来像

    # for banana, occurence of each char in alphabet
    [3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    

    所以构建它

    from string import ascii_lowercase
    
    def sorter(word: str):
        word_low = word.lower()
        return [word_low.count(c) for c in ascii_lowercase]
    
    values = ["Banana", "Isle", "Best", "Barb"]
    values = sorted(values, key=sorter, reverse=True)
    print(values)
    

    【讨论】:

      【解决方案3】:

      虽然这种方法有一些准备工作并且相对较长,但它在小列表中的表现相当不错,在非常大的列表中表现得非常好。它的主要优点是:

      • 它即时计算频率计数,每个单词仅计算一次。
      • 唯一的排序是在单词列表本身上完成的。
      • 比较器内不会重复额外的计算。

      所以首先建立一个比较器。

      • 首先比较数组中第一个位置的值(a 计数)。
      • 然后使用thenComparing 附加下一个计数的每个可能位置
      • 最后,反转整个比较器以倒序排序。
      Comparator<int[]> comp = Comparator.comparing(a -> a[0]);
      for (int i = 1; i < 26; i++) {
          final int g = i;
          comp = comp.thenComparing(a -> a[g]);
      }
      comp = comp.reversed();
      

      现在定义一个Function 来获取每个单词的字母频率计数。此函数接受一个单词并返回一个包含 26 个值的 int 数组,用于每个单词中字母 a-z 的计数。计数不区分大小写。

      Function<String, int[]> frequency = (word) -> {
          int[] counts = new int[26];
          for (char ch : word.toCharArray()) {
              counts[Character.toLowerCase(ch)
                      - 'a']++;
          }
          return counts;
      };
      

      现在该排序了。把它们放在一起:

      • 串流单词
      • 为每个单词创建一个Entry,其中key 是该单词,value 是为该单词计算的频率计数。
      • 然后使用之前构建的比较器对Entry#value 进行排序。
      • 并映射到键,并以列表形式返回。
      List<String> words = List.of("Banana", "Isle", "Best", "baha", "baby","bad", "animal", "zoo", "elephant");
      
      List<String> result = words.stream().map(
              word -> new AbstractMap.SimpleEntry<String, int[]>(
                      word, frequency.apply(word)))
              .sorted(Entry.comparingByValue(comp))
              .map(Entry::getKey).toList();
      
      System.out.println(result);
      

      打印

      [Banana, baha, animal, baby, bad, elephant, Best, Isle, zoo]
      
      
      

      【讨论】:

        猜你喜欢
        • 2021-12-27
        • 2020-06-13
        • 2015-08-25
        • 2014-08-30
        • 2012-03-26
        • 2019-07-13
        • 2018-02-23
        • 2021-11-09
        • 2015-09-11
        相关资源
        最近更新 更多