我使用bufio.Scanner将文件逐行读入变量wordlist([] [] byte)
这是代码(使用go 1.1 / 1.3进行测试)。
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
fle, err := os.Open("words.txt")
if err != nil {
log.Fatal(err)
}
defer fle.Close()
scanner := bufio.NewScanner(fle)
n := 1000
dCnt := 5
var wordlist [][]byte
for scanner.Scan() {
if len(wordlist) == n {
break
}
word := scanner.Bytes()
for ii := 0; ii < len(wordlist); ii++ {
if string(word) == string(wordlist[ii]) {
log.Println(ii, string(word), string(wordlist[ii]))
log.Println(len(wordlist), "double")
dCnt--
if dCnt == 0 {
for i, v := range wordlist {
fmt.Println(i, string(v))
}
log.Fatal("double")
}
}
}
wordlist = append(wordlist, word)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
words.txt是一个包含5040行序列排列的文件&#34; abcdefg&#34;:
line 1 ..
abcdefg
abcdegf
abcdfeg
abcdfge
..
line 510 ..
afcdbge
afcdebg
afcdegb
afcdgbe
afcdgeb
.. line 5040
由这个小python脚本生成:
from itertools import permutations as perm
c = "abcdefg"
p = perm(c, len(c))
with file('words.txt','wb') as outFle:
for i in xrange(5040):
n = ''.join(p.next())
print >> outFle, n
问题是,在运行上述go程序后,wordlist包含以下内容:
索引字符串(wordlist [])
0 afcdebg <-- this is line 513 of words.txt
1 afcdegb
2 afcdgbe
3 afcdgeb
...
510 bdefcag
511 bdefcga
512 afcdebg <-- this is the begin of a repition of line 513 .. 1024 in words.ttx
513 afcdegb
514 afcdgbe
相反,wordlist应该包含前1000行words.txt
任何想法?
答案由Daniel Darabos(见下文)提供。更改
word:= scanner.Bytes()
到
word:= scanner.Text()&#39;做了这个工作。
(感谢您的帮助!)
答案 0 :(得分:8)
Scanner.Bytes
的文档说:
基础数组可能指向将被后续调用Scan覆盖的数据。
因此,如果保存返回的切片,您可以期望看到其内容发生变化。这会对您的应用程序造成严重破坏。最好不要保存返回的切片!
一个很好的解决方案是从字节构建一个字符串:
word := string(scanner.Bytes())
然后你可以在任何地方使用字符串,代码变得更加愉快。
为什么Scanner.Bytes
恨我?答案也在文档中:
没有分配。
这使得扫描仪非常高效。从你看到的,我猜它在构造函数中为512行分配缓冲区,然后在它们上面旋转。
在不需要保留对行的引用的应用程序中,这不是问题。 (例如,类似grep
的程序只查看每一行。)通常,您解析该行并存储对该行的引用。但是如果要存储原始字节数据,则负责将其从Scanner
复制出来。
这可能很麻烦,但是虽然你可以在不方便的行为之上实现方便的行为,但是在低效行为之上实现有效行为是不可能的。
另一个用于生成输入的简单脚本:
import itertools
for p in itertools.permutations('abcdefg'):
print ''.join(p)