tags:

views:

113

answers:

7

How can i find different characters in the strings at same positions? Ex:

String string1 = "Anand has 2 bags and 4 apples";
String n = /* ??? */;
String n2 = /* ??? */;
String string2 = "Anand has " + n + " bags and " + n2 + " apples";

I want n = "2" and n1 = "4".

Please let me know how we can do this? (Space added between words only for clarity purpose . But i can not use Space as delimiter)

A: 

A regular expression should do this nicely.

matt-dot-net
Care to elaborate?
BalusC
Obligatory 'Some people, when confronted with a problem, think “I know, I'll use regular expressions.” Now they have two problems'.
whaley
@whaley... :D hahaha. That reminds me of a professor for my Computer Architecture class. His mentality was that "Everything can be done with XOR" :)
Hristo
@Hristo: ...but [everything CAN be done with XOR](http://everything2.com/title/XOR)!
Matt Ball
:D I wasn't denying the fact than everything can be done with XOR. I was just pointing out its entertainment factor :)
Hristo
A: 

You could use a for-loop to loop over the length of the smaller of the strings and check at each position individually

Nicolas78
A: 

If the lengths are not the same:

for(int i = 0; i < Math.min(str1.length, str2.length); i++){
    if(str1.charAt(i) != str2.charAt(i)){
        //Different
    }
}

for(int i = Math.min(str1.length, str2.length);
             i < Math.max(str1.length, str2.length); i++){
    //Each is in one but not the other.
}

If the lengths are the same:

for(int i = 0; i < str1.length; i++){
    if(str1.charAt(i) != str2.charAt(i)){
        //Different
    }
}
KLee1
A: 

I would split the Strings by "spaces", then I would do a for loop looking for numbers in the resulting array. Here's a little example, it's clumpsy but it gets the work done:

import java.util.ArrayList;

public class XXX{
    public static void main(String[] args){
        String str = "Anand has 2 bags and 4 apples";   

        System.out.println("Start...");
        System.out.println(str);
        String words[] = str.split("\\s+");

        ArrayList<String> values = new ArrayList<String>();

        for(String s:words){
            System.out.println(s);
            try{
                Integer.parseInt(s);
                values.add(s);
            }
            catch(NumberFormatException ex){
                System.out.println(s + " is not a number");
            }       
        }

        System.out.println("Anand has " + values.get(0) + " bags and " + values.get(1) + " apples");

    }
}
eiefai
+1  A: 

If you are sure about your text in the string remains same you can do something like this -

String string1 ="Anand has 2 bags and 4 apples";
String[] parts = string1.split("\\s+");
System.out.println("n = " + parts[2] + " n1 = " + parts [5]);
Gopi
+1  A: 

You can do:

String[] split = string1.split("\\s+"); // "\\s+" is a regex that will ignore any space, tab, etc from the String.

... this will return an array of the words:

{ split[0] = Anand, split[1] = has, split[2] = 2, ..., split[6] = apples }

From here you can just access the proper index of the array to extract the number. For example:

String n = split[2]; // n = 2 as a string

... or if you want it as an integer for later:

int n = Integer.parseInt(split[2]); // n = 2 as an int

Hope this helps.

Hristo
A: 

You can use the StringTemplate class that i developed (I'd developed a URITemplate class to match restlike uris but have modified it to use strings as well)

  // Licensed Apache2 (http://www.apache.org/licenses/LICENSE-2.0.txt) 
  import java.util.List;

  import java.net.URL;
  import java.net.URLConnection;

  import java.util.Map;
  import java.util.ArrayList;
  import java.util.LinkedHashMap;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;

  /**
   * <pre>
   *    StringTemplate t = new StringTemplate("/catalog/{categoryId}/products/{productId}/summary");
   *    t.matches("/catalog/23/products/12375/summary"); // returns true
   *    t.match("/catalog/23/products/12375/summary");   // returns a map {categoryId=23, productId=12375}
   * </pre>
   * 
   * @author anaik
   */
  public class StringTemplate {
     /** The meta pattern for  template to match sequence such as: {someVar} */
     private static final Pattern patternPattern = Pattern.compile("\\{([^\\{\\}]+)\\}");
     /** The  pattern string */
     private String stringPattern;
     /** The generated pattern when the stringPattern is parsed */
     private Pattern thisStringPattern;
     /** Variable names found in this pattern in that order */
     private List<String> vars = new ArrayList<String>();

     /**
      * Creates a new StringTemplate from the specified pattern
      * @param Pattern
      */
     private StringTemplate(String stringPattern)  {
        this.stringPattern = stringPattern;
        initialize();
     }

     /**
      * Gets the names of variables - those defined in {variable-name} constructs - in this StringTemplate
      * in the order they were specified
      * @return a list of variables or an empty list if no variables were found
      */
     public List<String> getVars() {
        return vars;
     }

     /**
      * Determine whether the specified <tt>actualString</code> matches with this StringTemplate
      * @param actualString The actual  to match
      * @return true iff successfull match
      */
     public boolean matches(String actualString)  {
        return thisStringPattern.matcher(actualString).matches();
     }

     /**
      * Matches the <tt>actualString</tt> with this StringTemplate and extracts values for all the variables
      * in this template and returns them as an ordered map (keys defined in the same order as that of
      * the StringTemplate. If the match was unsuccessfull, an empty map is returned. Note that this method
      * should be ideally be called after {@link #matches(java.lang.String) } to check whether the 
      * specified actually matches the template
      */
     public Map<String, String> match(String actualString) {
        Matcher m = thisStringPattern.matcher(actualString);
        Map<String, String> map = new LinkedHashMap<String, String>();
        if(m.matches())   {
           int gc = m.groupCount();
           for(int i = 0; i < gc; i++)   {
              int g = i + 1;
              map.put(vars.get(i), actualString.substring(m.start(g), m.end(g)));
           }
        }
        return map;
     }

     private void initialize()  {
        Matcher m = patternPattern.matcher(stringPattern);
        StringBuffer builder = new StringBuffer();

        while(m.find())   {
           String var = m.group(1);
           vars.add(var);
           m.appendReplacement(builder, "(.*)");
        }
        m.appendTail(builder);
        String genPattern = builder.toString();
        thisStringPattern = Pattern.compile(genPattern);
     }

     public static void main(String[] args) throws Throwable  {
        StringTemplate t = new StringTemplate(args[0]);
        System.out.println("Matches with actual Class Identifier: java.lang.String: " + t.matches(args[1]));
        System.out.println("Var values: " + t.match(args[1]));
     }
  }

Compile this and test as follows:

tmp$ java StringTemplate "Anand has {n} bags and {n1} apples" "Anand has 23 bags and 500 apples"

This is the output

 Matches with actual URI: true
 Var values: {n=23, n1=500}

The matches(String) returns the map containing the template variable names and values. This class can be used for matching any string with any number of vars. Its liscensed apache2

If your input string contains regex characters, you will have to escape them:

  input = input.replaceAll("\\$", "\\\\\\$");
  input = input.replaceAll("\\(", "\\\\(");
  input = input.replaceAll("\\)", "\\\\)");
  StringTemplate st = new StringTemplate(input);

Note that you need more accurate regexps for conditions where input string already has characters like "\$"

naikus
Thank you very much. I am looking this type of comparision. Because space added only for clarity purpose. But this doesnot match with any special cahracters. Correct? Is there way we can modify regular expression to match any character or special character. Means it has to match : $E(VAL,1,2)__$E(VAL,3,5)
vishnu
@vishnu, i tried this with:java StringTemplate "Anand has {n} bags and {n1} apples" "Anand has 23 bags and $E(VAL,1,2)__$E(VAL,3,5) apples"and got output:Var values: {n=3, n1=VAL,1,2)__(VAL,3,5) }
naikus
I tried $E(VAL,{i1},{i2})__$E(VAL,{i4},{i5}) with $E(VAL,1,2)__$E(VAL,3,5) but i got message: Matches with actual Class Identifier: java.lang.String: false Var values: {} .My template have all diffrent characters including double quotes("), spaces, colon, minus and so on...so please suggest me regular expression to match any
vishnu
Can you help me in this? I really want to done with this...Thank you for soon reply
vishnu
In case your input string already has regex characters, this will not work, You will have to escape all the regex characters before you create an instance of this class.String s = "$E(VAL,{i1},{i2})__$E(VAL,{i4},{i5})"; StringTemplate s = new StringTemplate(escape(s));The escape method will search for and escape all the regex characters
naikus
Thank you. But i am tring to escape $ in String s = "$E(VAL,{i1},{i2})__$E(VAL,{i4},{i5})"; with s = s.replaceAll("\\$", "\\\\$");but i am getting Error "java.lang.StringIndexOutOfBoundsException: String index out of range: 3". Please suggest me how to do this? Sorry for my basic question. Thank you very much for the support.
vishnu
@vishnu check my answer, i've edited my answer on how to escape chars. If it works for you, please mark this as the answer to your question :)
naikus
Thank you very much. Awesome solution. Thsi suits to match any paatern. Thanks once again
vishnu
How can i mark this as the answer to my question ?
vishnu
Just select my answer as the answer to your question
naikus