【问题标题】:How to count and sort letters in a string如何对字符串中的字母进行计数和排序
【发布时间】:2016-12-19 04:08:24
【问题描述】:

我想对用户输入的字母进行排序,并打印出用户字符串中每个字母的数量。这是我到目前为止所拥有的,我想知道这是否是正确的方法。我对java比较陌生,所以请让事情尽可能简单。根据我使用循环而不是大量 if else 构造的建议,我对我的代码进行了一些调整。这就是我所拥有的:

public class Assignment9
{
public static void main( String [] args )
{
    String user_string = Input.getString( "Please enter a string" );
    int length = user_string.length();
    int char_number = 1;
    int alphabet[] = new int[26];
    for( int repeats = 0 , repeats <= length , repeats++ )
    {
        char letter = user_string.charAt( char_number );
        char to_be_tested = Character.toLowerCase( letter );
        int subscript = 0;
        for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
        {
            char tester = (char) letter_number;

            if( to_be_tested == tester )
            {
                alphabet[subscript]++;
                subscript++;
            }
        }
        char_number++;
    }
    display( alphabet );
}
public static void display( int alphabet[] )
{
    int letter = 65;
    for( int a = 0; a < alphabet.length; a++ )
    {
        char character = ( char )letter;
        System.out.println ( "letter " + character + " count is " + alphabet[a] );
        letter++;
    }
}
}

我收到这些错误

Compilation errors:

test.java:9: error: ';' expected
            for( int repeats = 0 , repeats <= length , repeats++ )
                                          ^
test.java:9: error: illegal start of expression
            for( int repeats = 0 , repeats <= length , repeats++ )
                                           ^
test.java:9: error: ';' expected
            for( int repeats = 0 , repeats <= length , repeats++ )
                                             ^
test.java:9: error: illegal start of expression
            for( int repeats = 0 , repeats <= length , repeats++ )
                                                     ^
test.java:9: error: ')' expected
            for( int repeats = 0 , repeats <= length , repeats++ )
                                                      ^
test.java:9: error: illegal start of expression
            for( int repeats = 0 , repeats <= length , repeats++ )
                                                                 ^
test.java:14: error: ';' expected
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                              ^
test.java:14: error: illegal start of expression
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                               ^
test.java:14: error: ';' expected
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                                 ^
test.java:14: error: illegal start of expression
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                                      ^
test.java:14: error: ')' expected
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                                       ^
test.java:14: error: illegal start of expression
                    for(int letter_number = 97 , letter_number <= 122 , letter_number++ )
                                                                                        ^
12 errors

【问题讨论】:

  • 您的老师教过您什么是循环吗?你可以试试用一个吗?此外,您应该修复代码中的语法错误,StackOverflow 不允许这样的简单语法问题。
  • 为很棒的 if/else 语句点赞
  • 如果你所说的“真棒”意味着可怕。
  • @markspace 为一个可怕的代码付出了巨大的努力
  • 确实很恐怖。 OP 我建议你看看数组的用法,你的代码太臃肿了,你想要做的事情可以很容易地用像Array.indexOf(element) 这样的预构建函数来完成。例如,您可以使用它来匹配单词中的字母与数组的索引并增加该索引。

标签: java


【解决方案1】:

这是一种更简单的字母计数方法,忽略大小写:

final int[] chars = new int[26];
for (char c : value.toLowerCase().toCharArray()) {
  if ((c >= 'a') && (c<= 'z')) {
     chars[c - 'a']++;
  }
}

演示:https://repl.it/CmYR/0

【讨论】:

  • value 是你要测试的字符串,比如user_string
【解决方案2】:

事情是正在做所有的工作。您需要做的是让 COMPUTER 工作。所有这些打印报表都无缘无故地大量复制粘贴。因此,使用循环是一种更有效的方法。既然你已经知道循环,你可以想出这个解决方案-

import java.io.*;

public class experiments {
public static void main(String[] args) throws IOException {

    //Scanner sc=new Scanner(System.in);
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    int i,j;
    char chr;
    int len,count=0;
    System.out.println("Enter text-->");
    String str=br.readLine();
    str=str.toUpperCase();
    len=str.length();
    for(i='A';i<='Z';i++)
    {
        for(j=0;j<len;j++)
        {
            chr=str.charAt(j);
            if(chr==i)count++;              
        }
        System.out.println((char)i+"-->"+count);
        count=0;
    }
  }
}

【讨论】:

  • 你能解释一下这个是如何工作的吗?我真的很想在以后的程序中使用您在此处使用的一些关键字。
  • 第一件事是我们正在接受一个字符串输入并将其转换为大写(继续阅读,你会明白我为什么这样做:)...)。
【解决方案3】:

更简单的方法是使用地图数据结构。它存储(键,值)对。在您的情况下,键是字母,值是表示计数的整数。因此,当您遇到说“a”时,您会执行 yourMap.get('a') 并增加与该键配对的值。

在这里你可以阅读java中的地图:https://docs.oracle.com/javase/7/docs/api/java/util/Map.html

【讨论】:

    【解决方案4】:

    我更愿意在这里使用地图来存储每个字母的计数:

    Map<Character, Integer> letterMap = new HashMap<>();
    String userString = Input.getString( "Please enter a string" );
    
    for (int i=0; i < userString.length(); ++i) {
        char letter = userString.charAt(i);
        Integer value = letterMap.get(letter);
    
        letterMap.put(letter, value == null ? 1 : value.intValue() + 1);
    }
    
    for (Map.Entry<Character, Integer> entry : letterMap.entrySet()) {
        System.out.println("Letter '" + entry.getKey() + "' appeared " + entry.getValue() + " times.");
    }
    

    正如@Stephank 指出的那样,此解决方案不会打印输入中根本没有出现的字母的任何摘要统计信息。如果要打印 所有 个字母的统计信息,即使它们没有出现,也可以使用以下代码为地图播种:

    for (char letter = 'a'; letter <= 'z'; ++letter) {
        letterMap.put(letter, 0);
    }
    

    【讨论】:

      【解决方案5】:

      使用 Java 8 流

          String data = "some letters to count";
      
          Stream.of(data.split("(?!^)"))
                .collect(Collectors.groupingBy(Function.identity(), TreeMap::new, Collectors.counting()))
                .forEach((key, value)->System.out.println(key+": "+value));
      

      下面是解释:

      1. 首先,我们使用正则表达式将数据拆分为一个字母字符串:data.split("(?!^)");我们得到一个String的数组。

        0 = "s" 1 = "o" 2 = "m" 3 = "e" 4 = " " 5 = "l" 6 = "e" 7 = "t" 8 = "t" 9 = "e" 10 = "r" 11 = "s" 12 = " " 13 = "t" 14 = "o" 15 = " " 16 = "c" 17 = "o" 18 = "u" 19 = "n" 20 = "t"

      2. 我们从上述数组中创建一个StreamStream.of(data.split("(?!^)"))

      3. 在这一步中,我们使用groupingBy Collector 并传递TreeMap(将保持MapEntry 按键排序的SortedMap 实现)进行所有排序和计数:.collect(Collectors.groupingBy(Function.identity(), TreeMap::new, Collectors.counting()))

        此步骤的结果是排序后的TreeMap,其中不同的单个字符String 作为键,该字符的计数作为值。

        0 = {TreeMap$Entry@755} " " -> "3" 1 = {TreeMap$Entry@756} "c" -> "1" 2 = {TreeMap$Entry@757} "e" -> "3" 3 = {TreeMap$Entry@758} "l" -> "1" 4 = {TreeMap$Entry@759} "m" -> "1" 5 = {TreeMap$Entry@760} "n" -> "1" 6 = {TreeMap$Entry@761} "o" -> "3" 7 = {TreeMap$Entry@762} "r" -> "1" 8 = {TreeMap$Entry@763} "s" -> "2" 9 = {TreeMap$Entry@764} "t" -> "4" 10 = {TreeMap$Entry@765} "u" -> "1"

      4. 最后我们打印结果:.forEach((key, value)-&gt;System.out.println(key+": "+value));

      【讨论】:

        猜你喜欢
        • 2021-09-19
        • 2011-08-19
        • 1970-01-01
        • 2019-03-28
        • 2016-10-28
        • 2020-11-13
        • 1970-01-01
        相关资源
        最近更新 更多