【问题标题】:Find the most frequent element in a 2D String array & its number of occurrences查找二维字符串数组中出现频率最高的元素及其出现次数
【发布时间】:2021-02-27 08:32:03
【问题描述】:

我想问一下如何找到二维 String 数组中出现频率最高的元素以及该元素在 Java 中出现的次数?

更具体地说:

public static void mostFrequentElement(String[][] data) {
    // What should I write here?
}
String[][] data = {
        {"apple", "orange", "orange"},
        {"grape", "orange", "melon"},
};

mostFrequentElement(data);
// The function prints "orange 3" in the console
// This is because "orange" is the most frequent
// element in the data array and it showed up 3 times

我尝试使用HashMap,但我对它感到困惑,因为我是 Java 的初学者。非常感谢!

【问题讨论】:

    标签: java arrays string multidimensional-array


    【解决方案1】:
    /*
     * import java.util.Arrays;
     * import java.util.Comparator;
     * import java.util.Map;
     * import java.util.function.Function;
     * import java.util.stream.Collectors;
     */
    public static void mostFrequentElement(String[][] data) {
        Arrays.stream(data) // returns Stream<String[]>
                // returns Stream<String>
                .flatMap(row -> Arrays.stream(row))
                // returns Map<String, Long>
                .collect(Collectors.groupingBy(
                        Function.identity(), Collectors.counting()))
                // returns Set<Map.Entry<String, Long>>
                .entrySet()
                // returns Stream<Map.Entry<String, Long>>
                .stream()
                // returns Optional<Entry<String, Long>>
                .max(Comparator.comparing(Map.Entry::getValue))
                .ifPresent(System.out::println);
    }
    

    对于您的示例数据,上面的代码显示...

    orange=3
    

    【讨论】:

      【解决方案2】:

      Java Stream API 以简洁的方式更容易做到:

      import java.util.Arrays;
      import java.util.Map;
      import java.util.function.Function;
      import java.util.stream.Collectors;
      
      public class Main {
          public static void main(String[] args) {
              String[][] data = {
                      {"apple", "orange", "orange"},
                      {"grape", "orange", "melon"},
              };
      
              Map.Entry<String, Long> entryWithTheMaxCount =
                      // Get a Stream<String[]> out of the String[][]
                      Arrays.stream(data)
                              // Flatten the Stream<String[]> to Stream<String>
                              .flatMap(Arrays::stream)
                              // Collect the flattened Stream into
                              // a frequency Map<String, Integer>
                              .collect(Collectors.groupingBy(
                                      Function.identity(), Collectors.counting()))
                              // The following function calls are required
                              // only to get the entry with max count
                              .entrySet()
                              .stream()
                              .max(Map.Entry.comparingByValue())
                              .get();
      
              System.out.println(entryWithTheMaxCount);
          }
      }
      

      输出:

      orange=3
      

      【讨论】:

        【解决方案3】:

        这看起来像是 HashMap 的工作。通过循环遍历 2d 数组并将元素添加到地图中,或者如果它们已经在地图中,则将它们的映射值增加 1,我们可以跟踪每个元素的出现次数。并且通过创建一个最大变量来保存迄今为止出现次数最多的变量并在循环中更新它,到循环结束时,它将保存出现次数最多的元素。这是我的实现,但请随时查看Java Documentation 的哈希图,因为它很有帮助。

        public static void mostFrequentElement(String[][] data) {
            //keeps track of maximum occurrences
            int max = 0;
            String maxElem = "";
            //mapping the strings to the number of occurrences
            HashMap<String, Integer> map = new HashMap<String, Integer>();
            //looping through the 2d array
            for (int i = 0; i < data.length; i++) {
                for (int j = 0; j < data[i].length; j++) {
                    // if current element is already in
                    // the map, increment its occurrence by 1
                    if (map.containsKey(data[i][j])) {
                        map.put(data[i][j], map.get(data[i][j]) + 1);
                    }
                    //if not, add it to the map with 1 occurrence
                    else {
                        map.put(data[i][j], 1);
                    }
                    // if the current element's occurrences is
                    // bigger than max so far, set it to the max
                    if (map.get(data[i][j]) > max) {
                        max = map.get(data[i][j]);
                        maxElem = data[i][j];
                    }
                }
            }
            //print out the maximum after looping through all the elements
            System.out.println(maxElem + " " + max);
        }
        

        【讨论】:

          【解决方案4】:

          视任务情况而定,第一种较快,最后一种较慢:

          String[][] data = {
                  {"apple", "orange", "orange"},
                  {"grape", "orange", "melon"}};
          
          Stream<String> stream = Arrays.stream(data).flatMap(Arrays::stream);
          
          1. 如果您想filter 某些元素并获取其中的count

            Long count = stream.filter(str -> str.equals("orange")).count();
            
            System.out.println(count); // 3
            
          2. 如果要获取distinct 元素的数组:

            String[] distinct = stream.distinct().toArray(String[]::new);
            
            System.out.println(Arrays.toString(distinct));
            // [apple, orange, grape, melon]
            

            或者你可以使用HashSet:

            HashSet<String> set = stream.collect(Collectors.toCollection(HashSet::new));
            
            System.out.println(set);
            // [orange, apple, grape, melon]
            
          3. 如果您想collect 重复地图:

            Map<String, Long> duplicates = stream.collect(
                    Collectors.groupingBy(Function.identity(), Collectors.counting()));
            
            System.out.println(duplicates);
            // {orange=3, apple=1, grape=1, melon=1}
            

          另见:How to find duplicate elements in array in effective way?

          【讨论】:

            【解决方案5】:

            此解决方案有 3 个步骤:

            1. 找出数组每个维度中元素的频率
            2. 每个维度的汇总结果
            3. 找到最大值
            public class Main {
              public static void main(String[] args) {
                String[][] data = {
                  {"apple", "orange", "orange"},
                  {"grape", "orange", "melon"},
                };
                HashMap<String, Long> finalHashMap = new HashMap<>();
                for (String[] row : data) {
                  HashMap<String, Long> oneDimensionResult =
                      Arrays.asList(row).stream()
                          .collect(
                              Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting()));
                  for (String s : oneDimensionResult.keySet()) {
                    if (finalHashMap.containsKey(s)) {
                      Long count = finalHashMap.get(s);
                      finalHashMap.put(s, oneDimensionResult.get(s) + count);
                    } else {
                      finalHashMap.put(s, oneDimensionResult.get(s));
                    }
                  }
                }
                Entry<String, Long> maxEntry = null;
                for (Entry<String, Long> entry : finalHashMap.entrySet()) {
                  if (maxEntry == null || entry.getValue().compareTo(maxEntry.getValue()) > 0) {
                    maxEntry = entry;
                  }
                }
                System.out.println(maxEntry.getKey() + ":" + maxEntry.getValue());
              }
            }
            
            

            【讨论】:

              猜你喜欢
              • 2011-05-07
              • 1970-01-01
              • 1970-01-01
              • 2019-08-15
              • 1970-01-01
              • 2011-09-09
              • 2017-07-18
              • 2012-11-03
              相关资源
              最近更新 更多