1

I have an input data stored in an arraylist. while iterating through the list the output is

Input ----------- [0 Overcast 1 High 2 Normal 3 Weak ]
Input ----------- [0 Rainy 1 Mild 2 High 3 Strong ]
Input ----------- [0 Rainy 1 Mild 2 Normal 3 Weak ]

and rule in another arraylist

Rule -----------[ 0 Overcast Yes, 0 Rainy 3 Strong No, 0 Rainy 3 Weak Yes, 0 Sunny 2 High No, 0 Sunny 2 Normal Yes]

I am expecting the output as

[0 Overcast 1 High 2 Normal 3 Weak Yes]
[0 Rainy 1 Mild 2 High 3 Strong No]
[0 Rainy 1 Mild 2 Normal 3 Weak Yes]

By looking into rule set I have to add label to input. For that I tried to match between input and rule set

for(String ruleSet : addRule){ //ruleset
 for(String lineSet : getLine){ //inputline
   if (lineSet.matches("(.*)"+ruleSet+"(.*)")) {
     System.out.println("got----------------"+lineSet+"***"+ruleSet);
     break;
   }
   else{
     System.out.println("Not found----------------"+lineSet+"***"+ruleSet);
   }
 }
}

But my result is like this

0 Overcast 1 High 2 Normal 3 Weak Yes is not matching with 0 Overcast Yes. Eventhough it is a subset.

Am I doing anything wrong.

USB
  • 6,019
  • 15
  • 62
  • 93

1 Answers1

2

If I understand correctly, you have two lists of String:

  1. getLine is a list of strings representing lines of input
  2. addRule is a list of strings representing rule sets.

Each rule contains several parts that need to match against the input line, and a result that should be used in case of a match.

(You seem to call this result "classpath", though that term has a very specific meaning in the context of Java).

So the line:

0 Overcast 1 High 2 Normal 3 Weak

Would match against the rule

0 Overcast

because it contains the substring "0 Overcast", but also against the rule:

0 Overcast 3 Weak

because the line contains the substrings "0 Overcast" and "3 Weak", even though the entire rule does not appear as a substring in the line.

I guess what you were looking for is a subset search, and maybe saw this answer and tried to use it, but doing a subset match between strings is complicated, and using a regular expression is possible, but a little trickier than what you tried, so I'd recommend trying to go with a simpler solution.

Specifically, just doing .matches("(.*)"+ruleSet+"(.*)") will not do what you want.

If I'm correct in my interpretation of your problem, let me know in the comments, and I'll try to help you find a solution.

Continued

So, assuming you have control of the rule set, I would probably make a Rule class that looks something like this:

public class Rule {
    public List<String> parts;
    public String result;

    public Rule(String result, String... parts) {
        this.parts = new ArrayList<>();
        for(String part : parts) {
            this.parts.add(part);
        }
        this.result = result;
    }

    public String match(String line) {
        for(String part : parts) {
            if (!line.contains(part)) return null;
        }
        return result;
    }
}

Notice how match is implemented: if any of the parts don't match, then the match fails.

(I used varargs for the constructor, but you can just pass a list if you want).

Then you can initialize the rule set like this:

List<Rule> ruleSet = new ArrayList<>();
ruleSet.add(new Rule("Yes", "0 Overcast"));
ruleSet.add(new Rule("No", "0 Rainy", "3 Strong"));
ruleSet.add(new Rule("Yes", "0 Rainy", "3 Weak"));
...

And when you loop against the rules, call match to get null if there's no match, or the result if there is a match.

for(Rule rule : ruleSet) {
    for(String line : getLine) {
       String result = rule.match(line);
       if (result != null) {
          ...

Alternatively, you can write the rules as regular expressions like this:

String rule = ".*0 Rainy.*3 Strong.*";
if(line.matches(rule)) {
    ...

But you should probably avoid regular expressions until you've had some time to learn about them. They're powerful tools, but have many caveats.


If you need to keep the rule set in a text file, then you're going to have to write a method to convert the lines into a Rule object, possibly as a different constructor. Here's one way to do it:

public class Rule {
    ...
    public Rule(String line) {
        this.parts = new ArrayList<>();
        String number = null;
        for (String s : line.split()) {
            if (s.equals("Yes") || s.equals("No")) {
                this.result = s;
                return;
            }
            if (number == null) {
                number = s;
            } else {
                this.parts.add(number + " " + s);
                number = null;
            }
        }
    }
Community
  • 1
  • 1
itsadok
  • 28,822
  • 30
  • 126
  • 171
  • but lineSet.matches("(.*)"+ruleSet+"(.*)") will match substring also right? and I tried the way as u said that also wont work because it matches between [0 Overcast 1 High 2 Normal 3 Weak] *** [0 Overcast]I am trying to match the substring – USB Jun 18 '14 at 11:56
  • Or is there any alternative way to store the ruleset and iterative through that? – USB Jun 18 '14 at 12:20
  • @SreeVeni If you have a rule set, you're probably going to have to iterate through it no matter what. I don't understand your first comment. – itsadok Jun 19 '14 at 04:11
  • what I was trying to say was..I tried removing the classpath from ruleset and matched,But still they are not matching with inputline – USB Jun 19 '14 at 04:26
  • changed to contains and edited all as you adviced again not matching.I think we have to match for the substrings. eg 0 Overcast 1 Hot 2 High 3 Weak **should match** 0 Overcast – USB Jun 19 '14 at 05:02
  • I changed my answer completely. Read it over and tell me if I'm on the right track. – itsadok Jun 19 '14 at 05:18
  • 1
    Yes excatly that is what I meant :) .And it is the part of decision tree prediction. – USB Jun 19 '14 at 06:11
  • This is my [rule file](http://pastebin.com/G4pz0w2t).So I need to read as u suggested instaed of storing simply storing them to list. – USB Jun 19 '14 at 09:23