Home > Software engineering >  how to check if a string contains any element of an array in Java?
how to check if a string contains any element of an array in Java?

Time:08-19

I need to check if a a string contains any element of a string array and if it does, i want to return it.

String Summary = "CD-YTO : SOME RANDOM WORDS";
    StringBuilder finalvalue =  new StringBuilder();
    String output =  null;
     String[] value = Summary.split(" ");
              for(int i = 0; i<value.length; i  ){
                  if(value[i].contains("CD-")){
                      finalvalue.append(value[i]);
                  }
              }
              if(finalvalue != null){
                  output = finalvalue.toString();
              }
              
             String[] array = {"CD-YTO","CD-TYU","CD-TYP"};
             if(Arrays.asList(array).contains(output)){
                System.out.println(output);
             }
             else{
                 System.out.println("Absent"); 
             }

This my code. But i want to use a method that involves less iteration. Is there i can reduce the code complexity?

CodePudding user response:

The solution for the problem as you presented it is below. However, after writing the whole thing and re-reading your question, I think you are just looking for tags in specific places of the input string (named summary in your example).

If you know that the string will always be of the form "<tag> : blah blah blah", and you have an array of possible tags, you can use more or less the same technique described below, but the regular expression you will need is much simpler: the one below matches a tag surrounded by spaces anywhere in the string, but if the tag will always be at the beginning, you could simply match against this expression

^(tag1)|(tag2)|(tag3)

, which can be generated with:

Stream.of(array).map(Pattern::quote).collect(Collectors.joining(")|(", "^(", ")");

, and then you can define a Pattern and a Matcher as indicated below.


Now, for the original answer:

You could concatenate the string array to create a regular expression (or Pattern, as Java calls them):

String summary = "CD-YTO : SOME RANDOM WORDS";
String[] array = { "CD-YTO", "CD-TYU", "CD-TYP" };

// Create a Stream with the array. Roughly equivalent to a loop
String myPatternString = Stream.of(array)
// Escape any special character in the original words in the array
.map(Pattern::quote)
// Add "positive lookbehind" and "positive lookahead" groups before and after every word.
// This will cause the words to match only when they are surrounded by spaces
// but without including those spaces in the output.
// The "^" and "$" bits take care of words appearing at the beginning or the end of the string
.map(word -> "(?<=^|\\s)"   word   "(?=$|\\s)")
// Combine all elements into a single string
.collect(Collectors.joining(")|(", "(", ")");

The above should give you a string with the form:

"((?<=^|\\s)CD-YTO(?=$|\\s))|((?<=^|\\s)CD-TYU(?=$|\\s))|((?<=^|\\s)CD-TYP(?=$|\\s))"

Because of the Pattern::quote bit, the original strings will probably be further modified so that they are interpreted literally, even if they contain special characters such as parentheses, hyphens, etc. I don't know exactly what Pattern.quote does to escape the strings, but you get the idea.

With that, you can create a Pattern and match it against your input string:

Pattern myPattern = Pattern.compile(myPatternString);
Matcher myMatcher = myPattern.matcher(summary);

while(myMatcher.find()) {
    System.out.println(myMatcher.group());
}

Note that Pattern.compile is a expensive operation. If the array is constant and does not change in every execution, you most likely want to store it as a constant in your class and reuse it:

public class MyTagSearcher {

    final Pattern thePattern;        

    public MyTagSearcher(String words...) {
        thePattern = Pattern.compile(Stream.of( // etc.));
    }

    public List<String> matches(String summary) {
        final Matcher aMatcher = thePattern.matcher(summary);
        
        // Pre-Java 9
        final List<String> retVal = new ArrayList<>();
        while(aMatcher.find()) {
            retVal.add(aMatcher.group());
        }
        // or, alternatively, in Java 9 and above
        final List<String> retVal = aMatcher.results().map(MatchResult::group).collect(Collectors.toList());

        return retVal;
    }
}

As a final warning: please note that I haven't tested any of this code; it should generally work but it might require minor tweaks.

CodePudding user response:

If the summary always starts with the string you're looking for, you can use

String summary = "CD-YTO : SOME RANDOM WORDS";
String[] array = {"CD-YTO","CD-TYU","CD-TYP"};
System.out.println(
  Arrays.stream(array)
      .filter(summary::startsWith)
      .findFirst()
      .orElse("Absent")
);

CodePudding user response:

        String summary = "CD-YTO : SOME RANDOM WORDS";
        String output = Arrays.stream(summary.split(" ")).filter(s -> s.contains("CD-")).collect(Collectors.joining())
        String[] array = { "CD-YTO", "CD-TYU", "CD-TYP" };
        if (Arrays.asList(array).contains(output)) {
            System.out.println(output);
        } else {
            System.out.println("Absent");
        }

CodePudding user response:

Another solution using Patten and Stream:

String[] array = { "CD-YTO", "CD-TYU", "CD-TYP" };
String summary = "CD-YTO : SOME RANDOM WORDS : CD-TYU";

String wordPattern = "(CD[^\s] )";

List<String> arrayList= Arrays.asList(array);
List<String> result =  Pattern.compile(wordPattern) // passing the pattern which needs to be find
        .matcher(summary)  // passing the input which will be matched against the pattern
        .results() // return a stream of match results 
        .map(MatchResult::group)
        .filter(arrayList::contains)
        .collect(Collectors.toList());
System.out.println(result);

Output [CD-YTO, CD-TYU]

  • Related