简体   繁体   English

在不使用索引的情况下有效地搜索 arrays?

[英]efficiently searching arrays without using index?

So I am making a text based rpg for a class. Currently the functionality is working for one room which is all I currently want.所以我正在为 class 制作一个基于文本的角色扮演游戏。目前该功能适用于一个房间,这正是我目前想要的。 However I want a more efficient way of doing this.但是我想要一种更有效的方法来做到这一点。 I want to do this without indexes.我想在没有索引的情况下执行此操作。 I want to print a list of elements from the text file from contains(3.a) to the point where end.3 is.我想打印文本文件中的元素列表,从 contains(3.a) 到 end.3 所在的位置。 Can any of you vets help me?你们中的任何兽医都可以帮助我吗? . . This is my first attempt at this type of project.这是我第一次尝试此类项目。 The reason I am asking this early is because this is the intro into the project and the final project at the end of the semester will be a parsed 40 page text file.我这么早问的原因是因为这是项目的介绍,学期末的最终项目将是一个经过解析的 40 页文本文件。

The text file文本文件

1.a

Outside building
-------
WEST       2
UP         2
NORTH      3
IN         3

end.1

2.a

End of road
You are at the end of a road at the top of a small hill.
You can see a small building in the valley to the east.
------
EAST      1
DOWN      2

end.2

3.a

Inside building
You are inside a building, a well house for a large spring
-------
SOUTH    1
OUT      1

end.3

The code代码

public static void main(String[] args)throws FileNotFoundException{ 
    
    
    int direction = 0;
    Scanner s = new Scanner(new File("C:\\Users\\Basil Sheppard\\eclipse-workspace\\software practice\\src\\software\\rooms.txt"));
    Scanner choice = new Scanner(System.in);
    ArrayList<String> listS = new ArrayList<String>();
    

    while ( s.hasNextLine()) 
        listS.add(s.nextLine());
    
    
    System.out.println("please enter 3 for testing");
    direction = choice.nextInt();

    switch (direction){

//tests for room 3  
    case 3: {
    boolean found = listS.contains("3.a");
    if(found) {
        for(int i = 22; i<27; i++) {
            System.out.println(listS.get(i));
        }
    }
                            
} 

Your approach looks entirely wrong.您的方法看起来完全错误。

What I would do:我会做什么:

  1. Create a class MapLocation, with the following:使用以下内容创建一个 class MapLocation:
    1. Title, String标题,字符串
    2. Description, String[]描述,字符串[]
    3. Navigation, MapNavi[]导航,MapNavi[]
  2. Create another class MapNavi, with the following:使用以下内容创建另一个 class MapNavi:
    1. MapLoc, int MapLoc, 整数
    2. Direction, String方向,字符串
  3. Read and parse entire file into MapLocation[]读取整个文件并将其解析为 MapLocation[]
  4. Process input and traverse MapLocation[]处理输入并遍历 MapLocation[]

The structure of the file seems to be:该文件的结构似乎是:

(#.a

Title
Description Lines*
-------
MapNavi+

end.#)+

So you could either build a parser to process the file as above, which is quite trivial.所以你可以构建一个解析器来处理上面的文件,这很简单。 You could also parse the entire file using purely RegEx.您还可以使用纯 RegEx 解析整个文件。

Sample parser:示例解析器:

try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(_FILE_NAME))))
{
    String line;
    int state = 0;
    MapLocation currSegment = null;
    while ((line = br.readLine()) != null)
    {
        switch (state)
        {
        case 0:
           if (line.endsWith(".a"))
           {
               String segId = line.substring(0, line.indexOf(".a"));
               currSegment = new MapLocation(Integer.parseInt(segId));
               state++;
           }
           break;
        case 1:
           if (line.length() != 0)
           {
               currSegment.setTitle(line);
               state++;
           }
        case 2:
           if ("-------".equals(line))
           {
               state++;
           } else if (line.length() > 0)
           {
               currSegment.addDescription(line);
           }
        case 3:
           if (line.equals("end." + currSegment.getSegId()))
           {
               mapLocations.put(currSegment.getSegId(), currSegment);
               currSegment = null;
               state = 0;
           } else if (line.length() > 0)
           {
               String[] nav = line.split("\t");
               Integer mapLoc = Integer.parseInt(nav[1]);
               currSegment.addNavi(mapLoc, nav[0]);
           }
        }
    }
}

Once the file is parsed into the mapLocations container, you are ready to process input:一旦文件被解析到 mapLocations 容器中,您就可以处理输入了:

try (Scanner in = new Scanner(System.in))
{
    MapLocation currLoc = // startLocation;
    while (!quitSignal.equals(line = in.nextLine()))
    {
        int mapLoc = Integer.parseInt(line);
        if (currLoc.validateNav(mapLoc))
        {
            currLoc = mapLocations.get(mapLoc);
            System.out.println("You travel to " + currLoc.getTitle());
            System.out.println(currLoc.toString());
        }
        else
        {
            System.out.println("You cannot travel to location '" + line + "' from here.  Please re-select your destination.");
        }
    }
}

You should look into storing your path as an xml file.您应该考虑将路径存储为 xml 文件。 Java has some cool ways to read them and it can understand elements in a list. Java 有一些很酷的阅读方式,它可以理解列表中的元素。 You can even write to xml for easier constructing your game: Check this out for how to read in xml: https://stackoverflow.com/a/428091/9789673您甚至可以写信给 xml 以便更轻松地构建您的游戏:查看如何读取 xml: https://stackoverflow.com/a/428091/9789673

Try this.试试这个。

try (Scanner s = new Scanner(new File("C:\\Users\\Basil Sheppard\\eclipse-workspace\\software practice\\src\\software\\rooms.txt"))) {
    Scanner choice = new Scanner(System.in);
    ArrayList<String> listS = new ArrayList<String>();

    while (s.hasNextLine())
        listS.add(s.nextLine());

     System.out.println("please enter 3 for testing");
    int direction = choice.nextInt();

    listS.stream()
        .dropWhile(x -> !x.equals(direction + ".a"))
        .takeWhile(x -> !x.equals("end." + direction))
        .forEach(System.out::println);
    System.out.println("end." + direction);
}

output output

3.a

Inside building
You are inside a building, a well house for a large spring
-------
SOUTH    1
OUT      1

end.3

Note that .takeWhile(x ->.x.equals("end." + direction)) discards end.3 itself.请注意.takeWhile(x ->.x.equals("end." + direction))丢弃end.3本身。

I think you need to think about two main things:我认为你需要考虑两个主要问题:

  • Structure your file so that its lines have a fairly consistent structure that is easy to parse.构建文件,使其行具有易于解析的相当一致的结构。
  • Think about how you can organise your code so that you only scan through the file once, creating classes to store the data in memory in an organised way the first time you read through the file.想一想如何组织代码以便只扫描文件一次,在第一次阅读文件时创建类以有组织的方式将数据存储在 memory 中。 (Yes, in a sense, this is an "index", but you can't have it both ways: either you store/index information from the file the first time you scan it, or you throw the information away and have to scan through it again on the next query, which is inherently inefficient.) (是的,从某种意义上说,这是一个“索引”,但你不能同时拥有它:要么在第一次扫描文件时从文件中存储/索引信息,要么丢弃信息并必须扫描在下一个查询中再次通过它,这本质上是低效的。)

For example, you might structure your file something like this:例如,您可以像这样构建文件:

BEGIN:LOCATION:1
BEGIN:DESCRIPTION:
A house.
END:DESCRIPTION
BEGIN:DIRECTIONS
NORTH:3
SOUTH:4
END:DIRECTIONS
END:LOCATION

In other words, the lines generally consist of 'command':'subcommand', and given a line in the file, it is fairly easy to split this into its components (look at String.indexOf(), String.substring(). If you can, look at the regular expressions API: see the Pattern and Matcher classes. (Theoretically, this can bring some efficiencies when you are trying to scan the same line/text for a number of different patterns/substrings simultaneously, and is the approach you'd generally use if you were scanning large volumes of text for more complex patterns/commands. For your purposes, you would also be fine with the simple String methods-- indexOf(), substring() etc-- if you find these easier to get to grips with.)换句话说,这些行通常由 'command':'subcommand' 组成,并且给定文件中的一行,很容易将其拆分为其组件(查看 String.indexOf()、String.substring()。如果可以,请查看正则表达式 API:查看 Pattern 和 Matcher 类。(理论上,当您尝试同时扫描同一行/文本以查找多个不同的模式/子字符串时,这会带来一些效率,并且是如果您正在扫描大量文本以查找更复杂的模式/命令,则通常会使用这种方法。出于您的目的,您也可以使用简单的字符串方法——indexOf()、substring() 等——如果你发现这些更容易掌握。)

Others have mentioned XML: this is one a structured format that you could also consider, and comes with the advantage of standard parsing routines built into the Java platform.其他人提到了 XML:这是一种您也可以考虑的结构化格式,并且具有内置于 Java 平台中的标准解析例程的优势。 But there's nothing inherently wrong with a plain old text file in a format that you've devised so long as it's consistent and it's easy to write a routine to parse it...但是,只要它是一致的并且很容易编写例程来解析它,您设计的格式的纯旧文本文件就没有本质上的错误......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM