【问题标题】:How to restrict Matcher or Pattern in java?如何在java中限制匹配器或模式?
【发布时间】:2018-03-21 19:50:35
【问题描述】:

如何限制 Java 中的 Matcher 只匹配所需的 String ?以下是我尝试过的代码,但是预期的匹配应该是“收到发票”,但它在控制台上只打印“发票”。

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JavaTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<String> actionList = new ArrayList<String>();
        actionList.add("Invoice");
        actionList.add("Invoice Received");

        List<String> notes = new ArrayList<String>();
        notes.add("Invoice Received123");

        for (String note : notes) {
            for (String action : actionList) {

                Pattern pattern = Pattern.compile(action);
                Matcher matcher = pattern.matcher(note);

                if(matcher.find()) {
                    System.out.println("Update History As : "+action);

                }
            }
        }

    }

}

【问题讨论】:

  • 如果你只是想搜索一个字符串,为什么不直接使用 String.indexOf() 而不是模式匹配
  • 您搜索Invoice,找到并打印出来,然后跳出循环,根本不运行Invoice Received 部分。当然,这完全是对正则表达式的滥用。
  • @brso05 它只打印“Invoice”,但我们只需要“Invoice Received”作为输出

标签: java


【解决方案1】:
            if(matcher.find()) {
                System.out.println("Update History As : "+action);
                break;
            }

这破坏了您的代码。字面上地。当存在模式匹配时,break 语句退出内部 for 循环。结果,Invoice Recieved 永远没有机会被匹配。

最初这是被解释的问题,但后来问题变成了关于这个特定问题的流量控制。作为建议的解决方案,这里是Note 对象的示例没有 多态性,而是一个控制代码。

public class Note {
    public static final int INVOICE = 1;
    public static final int INVOICE_RECEIVED = 2;

    public int noteType;
    public String userText;

    public Note(int noteType, String userText) {
        this.noteType = noteType;
        this.userText = userText;
    }

    public void doSomething() {
        switch(noteType) {
            case INVOICE:
                // do something with the INVOICE type
                break;
            case INVOICE_RECEIVED:
                // do something with the INVOICE_RECEIVED type
                break;
         }
    }

}

然后,您可以创建一个由Note newNote = new Note(Note.INVOICE_RECEIVED, "this is some user text"); 接收的发票Note 对象并将它们添加到列表中,类似于您正在执行的操作,并相应地处理它们。根据您拥有的笔记数量,多态设计可能会更好,或者至少更干净。但这是使用控制代码的方式。

【讨论】:

  • 我刚刚编辑了我的问题,我只想要“收到发票”,请您现在检查一下吗?
  • 您正在将“发票”和“收到的发票”添加到 actionsList,这是一个 ArrayList。然后循环遍历每个actionArrayList。因此,您可以从ArrayList 中删除“发票”,也可以不使用循环和数组列表,只搜索一个字符串。您的代码的工作方式是在actionsList 中搜索所有actions。
  • 正确,数组列表中有多个值,我们需要,但是根据我们在“notes”列表中收到的值,我们需要从“actions”列表中找到匹配的值并点击用该值更新。例如“收到的发票”应该用作更新,因为我们在备注中得到了这一点
  • 远离 Matcher,任何其他的实现方式或建议也可以:),你能提出一些建议吗?
  • 老实说,我对您期望您的代码执行的操作感到困惑 - 您只希望它匹配“收到的发票”,但您正试图让它同时匹配“发票” " 和 "Invoice Received" 并输出匹配的内容?您的代码的工作方式是它会输出 actionsList 中的任何匹配项,而不仅仅是第一个匹配项 - 中断会停止这种情况,但它仍然不能保证您会找到 best match - 而只是第一个完全匹配的。
【解决方案2】:

您需要对要查找的模式进行排序,以便一种模式的前缀始终位于该模式之后。具体来说:

List<String> actionList = new ArrayList<String>();
actionList.add("Invoice Received"); /* Make this take precedence... */
actionList.add("Invoice");          /* ... over this. */

然后将break 放回您的匹配箱中,否则每个“已收到发票”的备注也将作为“发票”备注处理:

if(matcher.find()) {
  System.out.println("Update History As : "+action);
  break;
}

一般来说,这种系统很容易出现错误。如果您对此过程的输入有任何控制权,请对其进行修改,使注释类型是明确的,而不是从其内容中猜测出来。

【讨论】:

  • 这里唯一的问题是,我们必须将 note 的值与 action 进行比较,这是因为 note 部分是手动的,即根据用户的选择操作 + 文本的组合 & 所以我们正在这样做,请问有什么建议吗?
猜你喜欢
  • 2015-04-28
  • 1970-01-01
  • 2015-08-31
  • 2012-04-14
  • 2015-01-10
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多