【问题标题】:Match a string from a list and extract values匹配列表中的字符串并提取值
【发布时间】:2018-08-17 12:17:08
【问题描述】:

在 Java 中实现以下目标的最有效(低 CPU 时间)方法是什么?

假设我们有一个字符串列表,如下所示:

1.T.methodA(p1).methodB(p2,p3).methodC(p4)
2.T.methodX.methodY(p5,p6).methodZ()
3 ...

在运行时,我们得到的字符串可能与列表中的一个字符串匹配:

a.T.methodA(p1Value).methodB(p2Value,p3Value).methodC(p4Value) // Matches 1
b.T.methodM().methodL(p10) // No Match
c.T.methodX.methodY(p5Value,p6Value).methodZ() // Matches 2

我想将 (a) 与 (1) 匹配并提取 p1、p2、p3 和 p4 的值 其中:

p1Value = p1, p2Value = p2, p3Value = p3 and so on.

对于其他匹配,例如 c 到 2 也是如此。

【问题讨论】:

  • 效率需要一个维度。在运行时(CPU 时间)、代码长度、内存使用方面效率最高......?
  • 在 CPU 时间方面的效率。

标签: java string match


【解决方案1】:

我想到的第一个方法当然是正则表达式。

但这在未来更新或处理套期保值案件时可能会很复杂。

您可以尝试使用 Nashorn 引擎,它允许您在 jvm 中执行 javascript 代码。

所以你只需要创建一个特殊的 javascript 对象来处理你所有的方法:

private static final String jsLib = "var T = {" +
        "results: new java.util.HashMap()," +
        "methodA: function (p1) {" +
        "   this.results.put('p1', p1);" +
        "   return this;" +
        "}," +
        "methodB: function (p2, p3) {" +
        "   this.results.put('p2', p2);" +
        "   this.results.put('p3', p3);" +
        "   return this;" +
        "}," +
        "methodC: function (p4) {" +
        "    this.results.put('p4', p4);" +
        "    return this.results;" +
        "}}";

这是一个简单的字符串,而不是处理你的第一个案例。 您可以在 js 文件中编写代码并轻松加载该文件。

您在 javascript 对象中创建了一个特殊属性,即 Java HashMap,因此您可以将其作为评估的结果,并按名称列出所有值。

所以你只需评估输入:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

final String inputSctipt = "T.methodA('p1Value').methodB('p2Value','p3Value').methodC('p4Value')";

try {
    engine.eval(jsLib);

    Map<String, Object> result = (Map<String, Object>)engine.eval(inputSctipt);
    System.out.println("Script result:\n" + result.get("p1"));
} catch (ScriptException e) {
    e.printStackTrace();
}

你得到了:

脚本结果: p1值

以同样的方式,您可以获得所有其他值。

您需要忽略脚本错误,它们应该是未实现的路径。

请记住在每次评估之前重置脚本上下文,以避免与以前的值混合。

与正则表达式相比,这种解决方案的优点是易于理解,在需要时易于更新。

我能看到的唯一缺点是 JavaScript 知识,当然还有性能。

你没有提到性能是一个问题,所以如果你需要的话,你可以尝试这种方式。

如果您需要比正则表达式更好的性能。

更新

要获得更完整的答案,下面是正则表达式的相同示例:

Pattern p = Pattern.compile("^T\\.methodA\\(['\"]?(.+?)['\"]?\\)\\.methodB\\(['\"]?([^,]+?)['\"]?,['\"]?(.+?)['\"]?\\)\\.methodC\\(['\"]?(.+?)['\"]?\\)$");

Matcher m = p.matcher(inputSctipt);
if (m.find()) {
    System.out.println("With regexp:\n" + m.group(1));
}

请注意,此表达式不处理对冲情况,您需要为每个要解析和获取属性值的字符串使用 reg exp。

【讨论】:

  • 这是一个很好的解决方案。但是,就像您说的那样,我正在寻找更好的性能。您将如何使用正则表达式实现这一目标?
  • @Koba 我用一个正则表达式的例子更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2018-09-29
  • 2021-07-02
相关资源
最近更新 更多