检查字符串(句子空格分隔)以查看它是不是包含数组中的任何字符

Posted

技术标签:

【中文标题】检查字符串(句子空格分隔)以查看它是不是包含数组中的任何字符【英文标题】:Checking a String (sentence space separated) to see if it contains any of the chars in an array检查字符串(句子空格分隔)以查看它是否包含数组中的任何字符 【发布时间】:2022-01-17 16:14:52 【问题描述】:

我一直在尝试看看是否有办法通过双循环来解决这个问题。循环遍历数组中的每个单词并检查提供的所有字符是否都存在于该单词中。

键盘损坏问题:

输入 A =“你好,我亲爱的朋友!”

输入 B = ['h', 'e', 'l, 'o', 'm']

我们这里的键盘坏了,其中只有列表 B 中的字母键(小写和大写)、数字键和标点键起作用。

编写一个函数,它接受一个字符串 A 和一个字符 B 的列表,并返回我们可以输入多少个单词。

解释 输入:A “你好,我亲爱的朋友!”,B = ['h', 'e', 'l, 'o', 'm'] 输出:1

解释:对于第一个单词“Hello”(包括逗号),我们可以找到列表 B 中的每个字符。 由于所有标点键都可以正常工作,所以输出++。

对于第二个单词“my”,我们只能在列表 B 中找到 char 'm',因此无法输入整个单词。然后同样,“亲爱的”,找不到char 'd',所以继续; “朋友!”,找不到字符'f',所以继续;

这是我迄今为止尝试过的,但我不能使用 String 的 .contain() 方法,因为它只接受 char 序列而不是 char 数组。如何使用 JAVA 检查每个单词的字符数组?

提前致谢,感谢任何支持。

    public class BrokenKeyboard


   public static void main(String[] args)
   
      String stringText = "Hello my dear friend";
      char [] charLetterArray = 'h', 'e', 'l', 'o', 'm';

      howManyWordsCalc(stringText, charLetterArray);
   

   // Only words from stringText that can be typed in whole should be printed.
   // If the letters present in the word aren't present in charLetterArray they don't get printed
   public static int howManyWordsCalc(String text, char[] letters)
   
      int wordCount = 0;
      // sanitise input
      if (text.isEmpty())
      
         return 0;
      
      else
      
         text = text.toLowerCase();
         String[] stringSeparated = text.split(" ");

         for (int i = 0; i < stringSeparated.length; i++)
         
            System.out.println(stringSeparated[i]);

            for (int j = 0; j < letters.length; j++)
            
               // stringSeparated[i].contains(letters)
               if (stringSeparated[i].contains())
               
                  wordCount++;

               
            
         
         return wordCount;
      
   


【问题讨论】:

可以将char转成字符串String.contains(Character.toString(c)) 【参考方案1】:

这是一个示例解决方案:

public class Main

   public static void main(String[] args)
      String stringText = "Hello my dear friend";
      char [] charLetterArray = 'h', 'e', 'l', 'o', 'm';
      System.out.println(howManyWordsCalc(stringText, charLetterArray));
   

   // Only words from stringText that can be typed in whole should be printed.
   // If the letters present in the word aren't present in charLetterArray they don't get printed
   public static int howManyWordsCalc(String text, char[] letters)
      int wordCount = 0;
      // sanitise input
      if (text.isEmpty())
         return 0;
      
      else
         text = text.toLowerCase();
         String[] stringSeparated = text.split(" ");

         for (int i = 0; i < stringSeparated.length; i++)
            int validLetters = 0;
            for(int j = 0; j < stringSeparated[i].length(); j++)
              for(char c: letters)
                if(c == stringSeparated[i].charAt(j))
                  validLetters++;
                  break;
                
              
            
            if(validLetters == stringSeparated[i].length())
              wordCount++;
            
         
         return wordCount;
      
   


此代码的工作方式与您的完全相同,除了用于检查单词是否可以由可用字母组成的算法。

我首先遍历数组中每个单词的算法。然后,我创建了一个名为 validLetters 的整数,我们将在其中检查我们可以输入的单词中有多少个字母。如果validLetters的个数等于单词的长度,那么就可以输入单词了。

为了检查一个字母是否可以输入,我们将遍历单词中的每个字母,并查看它是否在数组 letters 内。如果是,我们增加validLetters并退出循环。

或者,如果您想在两个 for 循环中严格执行此操作,这是一个缩短版本:

import java.util.*;
public class Main

   public static void main(String[] args)
      String stringText = "Hello my dear friend";
      char [] charLetterArray = 'h', 'e', 'l', 'o', 'm';
      System.out.println(howManyWordsCalc(stringText, charLetterArray));
   

   // Only words from stringText that can be typed in whole should be printed.
   // If the letters present in the word aren't present in charLetterArray they don't get printed
   public static int howManyWordsCalc(String text, char[] letters)
      int wordCount = 0;
      // sanitise input
      if (text.isEmpty())
         return 0;
      
      else
         text = text.toLowerCase();
         String[] stringSeparated = text.split(" ");

         for (int i = 0; i < stringSeparated.length; i++)
            int validLetters = 0;
            for(int j = 0; j < stringSeparated[i].length(); j++)
              if (new String(letters).indexOf(stringSeparated[i].charAt(j)) != -1) 
                 validLetters++;
              
            
            if(validLetters == stringSeparated[i].length())
              wordCount++;
            
         
         return wordCount;
      
   


如果您有任何问题/澄清,请告诉我!

【讨论】:

太好了,非常感谢。两种解决方案都很棒,我更喜欢您的第二种解决方案。 if (new String(letters).indexOf(stringSeparated[i].charAt(j)) != -1) 在上面的行中,结果可能是-1 吗?? 如果字母不在单词中,那么语句将为-1。如果这是真的,那么 validLetters 的值将不会增加,因此永远不会达到单词的长度并且永远不会更新 wordCount。 是的,当然。再次感谢:) np 很乐意提供帮助【参考方案2】:

我稍微改了一下,看看:

public static void wordCalc(String input, char[] chars) 
    String[] inputWords = input.toLowerCase().split(" ");

    boolean[] allLetters = new boolean[26];
    for(int i=0; i<chars.length; i++) 
        allLetters[chars[i] - 'a'] = true;
    

    int wordCount = 0;
    for(String word : inputWords) 
        boolean isWordPossible = true;
        for(int i=0; i<word.length(); i++)
            if(!allLetters[word.charAt(i) - 'a'])
                isWordPossible = false;
                break;
            
        

        if(isWordPossible) 
            System.out.println("word " + word + " is possible");
            wordCount++;
        
    

    System.out.println(wordCount);

我曾经在互联网上发现了这个非常巧妙的技巧。将允许的字母存储在布尔数组中。这样,当您想检查是否允许使用 char 时,您只需检查与该字符对应的索引处的数组值!

然而,这确实让我注意到了一个重要的注意事项。字符存储为整数,这就是为什么你可以来回转换它们并做一些时髦的东西,比如word.charAt(i) - 'a'(这会给你在布尔数组中的位置,因为它会给你字母“a”和任何东西之间的距离字母在单词中的位置“i”)。

字符串最终是 char 数组。所以你可以这样做:

char[] stuff = someString.toCharArray();

同样重要的是要注意字符串是不可变的,字符串字面量指向同一个对象。

关于时间复杂度的最后说明,最好尽可能避免嵌套循环。如果你有大量的输入,它会变得非常慢!如果你有一个循环,它是 O(n) 时间,2 个循环它已经是 O(n^2),就时间复杂度而言,这是相当慢的。但是,对于这种情况,我想不出另一种方法。您使用的结构和访问方法会极大地影响性能。我想你会非常喜欢HashSets,尤其是对于这个允许的字符是唯一的问题。

【讨论】:

非常感谢,我从未见过布尔数组。我也很欣赏大 O 参考。是的,也许在这里创建一个哈希集是有益的。【参考方案3】:

您可以通过使用另一个循环(实际上与String::contains 具有相同的复杂性)来检查单词中的所有字符是否包含在letters 字符数组中。

另外,我建议通过使用[\pZ\pP]+ 正则表达式拆分重复的标点符号和/或空白字符来获取单词,其中\pZ 代表空格,\pP 代表标点符号。

public static int howManyWordsCalc(String text, char[] letters) 
    int wordCount = 0;
    
    String[] words = text.toLowerCase().split("[\\pP\\pZ]+");
    
    for (String word : words) 
        // System.out.print("'" + word + "'\t");
        boolean allFound = true;
        for (char c : word.toCharArray()) 
            boolean found = false;
            for (char letter : letters) 
                if (c == letter) 
                    found = true;
                    break;
                
            
            if (!found) 
                // System.out.println("not found letter: " + c + " in word " + word);
                allFound = false;
                break;
            
        
        if (allFound) 
            wordCount++;
            // System.out.println("all found");
        
    
    return wordCount;
    

测试:

System.out.println(howManyWordsCalc(
    "Hello, my dear friend!", new char[] 'h', 'e', 'l', 'o', 'm', 'y'
));

输出(启用调试打印):

'hello' all found
'my'    all found
'dear'  not found letter: d in word dear
'friend'    not found letter: f in word friend
2

【讨论】:

String[] words = text.toLowerCase().split("[\\pP\\pZ]+"); 太棒了,多么巧妙的把戏【参考方案4】:

我在 c# 中尝试过相同的方法,但您也可以使用 HashSet 集合并尝试相同的方法。 Java HashSet 也有 Contains()。

我希望这会有所帮助。

class Program

    static void Main(string[] args)
    
        string a = "Hello, my dear friend!";
        string A = a.ToUpper();
        string[] seperate = A.Split(new Char[]  ' ', ',', '.', '-', '\n', '\t', '!' );
        HashSet<Char> hash = new HashSet<char>();
        hash.Add('H');
        hash.Add('E');
        hash.Add('L');
        hash.Add('O');
        hash.Add('M');
        int count = 0;
        bool flag = true;
        foreach (var w in seperate)
        
            if (w.Length > 0)  
                Char[] ca = w.ToCharArray();
                foreach (var d in ca)
                
                    if(!hash.Contains(d))
                    
                        flag = false;
                        break;
                    
                
                if(flag)
                
                    flag = true;
                    count++;
                
            
        
        Console.WriteLine("Count : " + count);
        Console.Read();
    

【讨论】:

以上是关于检查字符串(句子空格分隔)以查看它是不是包含数组中的任何字符的主要内容,如果未能解决你的问题,请参考以下文章

我试图在数字数组上使用 .filter、.sort 和 .reduce 以返回由逗号和空格分隔的字符串

NSPredicate 检查以逗号分隔的一串数字是不是包含数字

将空格分隔的字符串读入 Bash 中的数组

如何检查句子是不是包含特定单词?

检查逗号分隔列表是不是包含特定数字[重复]

2021-10-16:单词拆分 II。给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。