如何在Java中实现复杂字符串的集合(列表、映射?)?

发布于 2024-08-30 04:42:36 字数 1344 浏览 4 评论 0 原文

问题——我有类似以下条目的内容,其中 1000 个:

args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
args1=msg args2=flow args3=content args4=depth args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=content args6=within ==> args5=content
args1=msg args2=flow args3=content args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=flow ==> args4=flowbits
args1=msg args2=flow args3=flow args5=content ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args5=content
args1=msg args2=flow args4=depth ==> args3=content
args1=msg args2=flow args4=depth args5=content ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within args7=distance ==> args3=content

我正在做某种建议方法。比如说,args1=msg args2=flow args3=flow ==> args4=flowbits

如果句子包含 msg、flow 和另一个 flow,那么我应该返回 flowbits 的建议。

我怎样才能到处做呢?我知道我应该扫描(每当在文本区域上按下一个字符时)列表或数组进行匹配并返回结果,但是,1000 个条目,我应该如何实现它?

我正在考虑 HashMap,但是我可以做这样的事情吗?

<“消息,流,流”,“流位”>

另外,在一个句子中,参数可能不按顺序排列,因此假设它是 flow,flow,msg 那么我无法匹配 HashMap 中的任何内容,因为键是“msg,flow,flow”。

这种情况我该怎么办?请帮忙。谢谢一百万!

Problem -- I have something like the following entries, 1000 of them:

args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
args1=msg args2=flow args3=content args4=depth args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=content args6=within ==> args5=content
args1=msg args2=flow args3=content args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=flow ==> args4=flowbits
args1=msg args2=flow args3=flow args5=content ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args5=content
args1=msg args2=flow args4=depth ==> args3=content
args1=msg args2=flow args4=depth args5=content ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within args7=distance ==> args3=content

I'm doing some sort of suggestion method. Say, args1=msg args2=flow args3=flow ==> args4=flowbits

If the sentence contains msg, flow, and another flow, then I should return the suggestion of flowbits.

How can I go around doing it? I know I should scan (whenever a character is pressed on the textarea) a list or array for a match and return the result, but, 1000 entries, how should I implement it?

I'm thinking of HashMap, but can I do something like this?

<"msg,flow,flow","flowbits">

Also, in a sentence the arguments might not be in order, so assuming that it's flow,flow,msg then I can't match anything in the HashMap as the key is "msg,flow,flow".

What should I do in this case? Please help. Thanks a million!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

寒冷纷飞旳雪 2024-09-06 04:42:37

换句话说,尽量不要在解析器中执行所有逻辑。拆分逻辑,以便解析器仅检测结构,然后构建对象来帮助您执行规则。解析器可以轻松检测参数并使用它们来创建列表。

如果您创建一个类来包含您的参数,如下所示:

public class Arg {
    public int number;
    public String value;

    public Arg(int num, String val) {
        this.number = num;
        this.value = val;
    }

    @Override
    public String toString()
    {
   return "[Arg num=" + number + ", value=" + value + "]";
    }

}

那么您可以将它们放入一个简单的哈希表中。

Map<Arg> argList = new HashMap<Arg>();

然后您可以使用计数器和 contains() 或 indexOf() 等来执行逻辑。

拥有 Arg 类也使排序变得容易。如果您需要按参数位置排序的列表,您可以为此创建一个比较器。

import java.util.Comparator;

public class ArgNumComparator implements Comparator<Arg> {
    public int compare(Arg o1, Arg o2) {
       if (o1.number == o2.number) {
        return 0;
       }
       return o1.number < o2.number ? -1 : 1 ;
   }    
}

按参数值排序甚至更容易,因为您可以重用字符串的compareTo()。

import java.util.Comparator;

public class ArgValComparator implements Comparator<Arg>
{
    public int compare(Arg o1, Arg o2)
   {
       return o1.value.compareTo(o2.value);
   }
}

然后,要进行排序,请使用 Collections.sort() ,如下所示:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArgList{
    public static void main(String[] args)  {
        //args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
        List<Arg> l = new ArrayList<Arg>();  
        // hard-coded example instead of more likely parsing
        l.add(new Arg(1, "msg"));
        l.add(new Arg(2, "flow"));
        l.add(new Arg(3, "content"));
        l.add(new Arg(4, "depth"));
        l.add(new Arg(5, "flow"));
        l.add(new Arg(6, "within"));

    Collections.sort(l, new ArgValComparator()); // take your pick of comparators

    System.out.println(l); // uses the toString() of Arg.
    }
}

编辑:向 Arg 添加 toString() 方法,并将示例中的列表更改为具有两个“流”参数。

使用新的 toString 代码运行会将以下内容输出到控制台:

[[参数编号=3,值=内容],[参数
num=4,值=深度],[参数num=2,
值=流量],[参数编号=5,值=流量],
[参数编号=1,值=消息],[参数编号=6,
值=内]]

正如您所看到的, value="flow" 的两个参数现在彼此相邻。要检测 value="flow" 的多个参数,可以这样做:

boolean flowFound = false;
for (Arg arg : l){
   if (arg.value.compareToIgnoreCase("flow") == 0) {
      if (flowFound)  //already found one? {
         // action when second "flow" exists
         System.out.println("2nd flow found");
      }
      else {
         flowFound = true;  // found the first "flow"
      }
   }          
}

In other words, try not to do all your logic in your parser. Split up the logic so the parser is simply detecting the structure and then build objects to help you enforce the rules. A parser can easily detect the arguments and use them to create a list.

If you create an class to contain your arguments like so:

public class Arg {
    public int number;
    public String value;

    public Arg(int num, String val) {
        this.number = num;
        this.value = val;
    }

    @Override
    public String toString()
    {
   return "[Arg num=" + number + ", value=" + value + "]";
    }

}

then you can put those in a simple Hashtable.

Map<Arg> argList = new HashMap<Arg>();

Then you can do the logic using maybe a counter and contains() or indexOf() etc.

Having the Arg class makes sorting easy too. If you need the list sorted by the argument position, you create a Comparator for that.

import java.util.Comparator;

public class ArgNumComparator implements Comparator<Arg> {
    public int compare(Arg o1, Arg o2) {
       if (o1.number == o2.number) {
        return 0;
       }
       return o1.number < o2.number ? -1 : 1 ;
   }    
}

Sorting by the argument value is even easier since you can reuse the comparedTo() of Strings.

import java.util.Comparator;

public class ArgValComparator implements Comparator<Arg>
{
    public int compare(Arg o1, Arg o2)
   {
       return o1.value.compareTo(o2.value);
   }
}

Then, to do the sorting use the Collections.sort() like so:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArgList{
    public static void main(String[] args)  {
        //args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
        List<Arg> l = new ArrayList<Arg>();  
        // hard-coded example instead of more likely parsing
        l.add(new Arg(1, "msg"));
        l.add(new Arg(2, "flow"));
        l.add(new Arg(3, "content"));
        l.add(new Arg(4, "depth"));
        l.add(new Arg(5, "flow"));
        l.add(new Arg(6, "within"));

    Collections.sort(l, new ArgValComparator()); // take your pick of comparators

    System.out.println(l); // uses the toString() of Arg.
    }
}

EDIT: added a toString() method to Arg and changed the list in the example to have two "flow" args.

Running with the new toString code puts the following to the console:

[[Arg num=3, value=content], [Arg
num=4, value=depth], [Arg num=2,
value=flow], [Arg num=5, value=flow],
[Arg num=1, value=msg], [Arg num=6,
value=within]]

As you can see, the two args with value="flow" are now next to each other. To detect multiple args where value="flow" can be done thus:

boolean flowFound = false;
for (Arg arg : l){
   if (arg.value.compareToIgnoreCase("flow") == 0) {
      if (flowFound)  //already found one? {
         // action when second "flow" exists
         System.out.println("2nd flow found");
      }
      else {
         flowFound = true;  // found the first "flow"
      }
   }          
}
自控 2024-09-06 04:42:37

是的,您可以执行 <"msg,flow,flow","flowbits">在哈希图中。这是最好的解决方案吗,我不知道。

yes, you can do <"msg,flow,flow","flowbits"> in a hashmap. Is it the best solution, I don't know.

还不是爱你 2024-09-06 04:42:37

乍一看,这看起来对于解析器和形式语法而不是集合来说是一个很好的用途。 ANTLR 是一个流行的 Java 解析器生成器。

解析器无法解决您的问题的是参数是否可以按任何顺序出现。在这种情况下,我将使用某种结合了规则和操作的 Case 对象,并使用简单的 Map> 来查找可能适用于给定的文本(您可以从文本中提取单个单词来探测地图,并且可以组合从每个探测返回的列表)。

我没有时间给出完整的示例,但 Case 对象可能如下所示:

public interface Case {
    boolean evaluate(String text);
    String result();
}

At first glance, this looks like a good use for a parser and formal grammar rather than a collection. ANTLR is a popular parser generator for Java.

Where a parser won't solve your problem is if the arguments can appear in any order. In that situation I would use some sort of Case object that combines rules and actions, and use a simple Map<String,List<Case>> to find the instances that might apply to a given text (you'd extract individual words from the text to probe the map, and could combine the lists returned from each probe).

I don't have the time to give a complete example, but the Case object would probably look something like this:

public interface Case {
    boolean evaluate(String text);
    String result();
}
以为你会在 2024-09-06 04:42:37

您可以创建一个对象并将每行的逻辑封装在其中。如果输入与描述完全相同,您应该能够使用简单的正则表达式和捕获组来提取参数,然后为每个参数调用对象上的设置器。那么你的数据结构将只是这些对象的列表。

You could create an object and encapsulate the logic within it for each line. If the input is exactly as described, you should be able to extract the args with a simple regular expression and capturing groups, then call setters on your object for each arg. Then your data structure would just be a list of these objects.

紫竹語嫣☆ 2024-09-06 04:42:37

由于字符串出现的顺序并不重要,因此您可以在创建密钥时按字母顺序排列它们。假设您想要相同的建议,msg,flow,flow 和 flow,msg,flow 和 flow,flow,msg - 按字母顺序排列,它们是“flow,flow,msg”,所以这就是您用作密钥的内容。

Since the order that the strings appear is not important, you can alphabetize them when you create the key. Suppose you want the same suggestion for, msg,flow,flow and flow,msg,flow and flow,flow,msg -- alphabetized, they are "flow,flow,msg", so that is what you use as the key.

廻憶裏菂餘溫 2024-09-06 04:42:36

Map 的键可以是另一个 MapSet。看起来你所需要的只是一个 Map, String> 或者一个 Map, Map.Entry> 。 - 不确定这些“args1”、“args2”在哪里相关。

A Map's key can be another Map or a Set. Looks like all you need is something like a Map<Set<String>, String> or perhaps a Map<Map<String, String>, Map.Entry<String, String>> - not sure where these "args1","args2" are relevant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文