如何在文件夹中找到每个单词的位置?

huangapple go评论74阅读模式
英文:

How to find location of each word in a folder?

问题

我正在尝试实现一个程序用于保存给定文件夹中所有单词及其位置例如有一个方法`wordLoc(File folder)`,它以父文件夹作为参数我使用递归方法遍历了父文件夹

然后我试图将每个单词的位置保存在`TreeMap<String, TreeSet<WordLocation>>`其中键是单词值是**WordLocation**对象的集合

WordLocation是一个具有路径行和列字段的类

```java
public class WordLocation {
    private String path;
    private int row;
    private int column;
    
    public WordLocation(String path, int row, int column) {
        this.path = path;
        this.row = row;
        this.column = column;
    }
}

我的方法如下所示:

private void wordLoc(File file) throws IOException {
    if (file.isFile()) {
        BufferedReader br = new BufferedReader(new FileReader(file));
        int ch;
        int row = 1, column = 0;
        String word = "";
        do {
            ch = br.read();
            column++;
            if (ch == '\n') {
                row++;
                column = 0;
            } else if (isValid((char) ch)) {
                word += (char) ch;
            } else {
                if (word.length() > 0) {
                    WordLocation location = new WordLocation(file.getPath(), row, column - word.length());
                    // WORD和LOCATION的映射在此处
                    word = "";
                }
            }
        } while (ch != -1);

        br.close();
    }
}

这里的助手方法isValid(char ch)只是检查字符是否有效(字母数字值):

private boolean isValid(char ch) {
    if ('a' <= ch && ch <= 'z') {
        return true;
    } else if ('0' <= ch && ch <= '9') {
        return true;
    }

    return false;
}

希望我选择的数据结构是保存单词及其位置的正确选择。如果是这样的话,我该如何进行映射呢?

例如,如果我在文件夹及其子文件夹的文件中搜索单词“Tokyo”,并且想要查看单词在文件中的每个位置,包括行号和列号,那么输出将会是这样的:

Tokyo:
filename: "ParentFolder\Cities\Cities.txt"; line:3; column:12
filename: "ParentFolder\Cities\Cities.txt"; line:4; column:31
filename: "ParentFolder\AnotherFolder\File.txt"; line:3; column:1

附注:我对其余部分有一个想法:遍历映射并检查搜索到的单词是否与映射中的单词相等,如果相等,我将遍历给定单词的所有位置并将其打印出来。


<details>
<summary>英文:</summary>

I&#39;m trying to implement a program that saves all words and their locations in given folder&#39;s files. For example, there is a method `wordLoc(File folder)` which takes a parent folder as a parameter. I did traversing of parent folder using recursive approach.

Then I&#39;m trying to save location of every word in `TreeMap&lt;String, Treeset&lt;WordLocation&gt;&gt;`, where key is word, and value is set of **WordLocation** objects:

WordLocation is a class with fields path, row, column:

    public class WordLocation {
        private String path;
        private int row;
        private int column;
        
        public WordLocation(String path, int row, int column) {
            this.path = path;
            this.row = row;
            this.column = column;
        }
    }

My method looks as follows:

    private void wordLoc(File file) throws IOException {
            if(file.isFile()) {
                BufferedReader br = new BufferedReader(new FileReader(file));
                int ch;
                int row = 1, column = 0;
                String word = &quot;&quot;;
                do {
                    ch = br.read();
                    column++;
                    if(ch == &#39;\n&#39;){
                        row++;
                        column = 0;
                    } else if(isValid((char)ch)) {
                        word += (char)ch;
                    } else {
                        if (word.length() &gt; 0) {
                            WordLocation location = new WordLocation(file.getPath(), row, column-word.length());
                            // MAPPING OF WORD AND LOCATION GOES HERE                  
                            word = &quot;&quot;;
                        }
                    }
                } while (ch != -1);
    
                br.close();
            }
        }

Helper method here `isValid(char ch)` just checks whether my char is valid (alphanumeric values):

    private boolean isValid(char ch) {
        if(&#39;a&#39; &lt;= ch &amp;&amp; ch &lt;= &#39;z&#39;) {
            return true;
        } else if(&#39;0&#39; &lt;= ch &amp;&amp; ch &lt;= &#39;9&#39;) {
            return true;
        }
    
        return false;
    }


Hope, DS I chose is a right choice for saving words and their locations. If so, how can I do mapping?

For example, if I search for word &quot;Tokyo&quot; in the folder and its subfolders&#39; files, and want to see every location of word in files with row, column numbers, it would like this:

    Tokyo:
    filename: &quot;ParentFolder\Cities\Cities.txt&quot;; line:3; column:12
    filename: &quot;ParentFolder\Cities\Cities.txt&quot;; line:4; column:31
    filename: &quot;ParentFolder\AnotherFolder\File.txt&quot;; line:3; column: 1

P.S. I have an idea about the rest: to iterate through map and see if searched word equals word in map, if so I would go through all locations of given word and simply print them. 

</details>


# 答案1
**得分**: 2

看起来您想要将一个词(例如'Tokyo')映射到一个WordLocation对象的__列表__。所以,让我们来做:

```java
private final Map<String, List<WordLocation>> locations = new HashMap<>();

要添加一个新词,需要分两步进行:

  1. 获取给定词的列表,并且,如果列表不存在,就创建一个列表。
  2. 将新创建的WordLocation添加到这个列表中。

我们可以在一行中完成这个操作:

map.putIfAbsent(word, w -> new ArrayList<WordLocation>()).add(location);

这将在箭头后面的代码(new ArrayList<WordLocation>())运行,但仅当键尚未在映射中时。然后,它将返回刚刚创建的内容,否则将返回与该键已关联的值,这正是我们想要的。然后我们只需在结果列表上调用add(location)

然后要查找内容,这很简单:

List<WordLocation> locations = map.getOrDefault("Tokyo", List.of());
for (WordLocation loc : locations) {
    System.out.println("  " + loc);
}

这将获取与"Tokyo"关联的值,如果没有,将返回一个空列表(这避免了以后需要写空指针检查的情况)。然后对您的列表进行任何操作。它也可能是空的。

英文:

Looks like you want to map a word, such as 'Tokyo', to a list of WordLocation objects. So, let's do that:

private final Map&lt;String, List&lt;WordLocation&gt;&gt; locations = new HashMap&lt;&gt;();

to add a new word, the job is two-fold:

  1. Fetch the list for the given word, and, if there is no list, create it.
  2. Add the newly created WordLocation to this list.

We can do that in one line:

map.putIfAbsent(word, w -&gt; new ArrayList&lt;WordLocation&gt;()).add(location);

That will run the code after the arrow (new ArrayList&lt;WordLocation&gt;()), but only if the key isn't in the map at all. Then, it will return either what you just made, or the value already associated with that key otherwise, which is precisely what we want. We then just invoke add(location) on the resulting list.

Then to look stuff up, that's trivial:

List&lt;WordLocation&gt; locations = map.getOrDefault(&quot;Tokyo&quot;, List.of());
for (WordLocation loc : locations) {
    System.out.println(&quot;  &quot; + loc);
}

This will fetch the associated value from Tokyo, and if there is none, that will return an empty list (this avoids having to then write nullchecks later). Then do whatever you want to your list. Which may be empty.

huangapple
  • 本文由 发表于 2020年9月23日 20:09:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/64027651.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定