我想使用python从文件中检索一个随机单词,但我不相信我的以下方法是最好或最有效的.请协助.
import fileinput
import _random
file = [line for line in fileinput.input("/etc/dictionaries-common/words")]
rand = _random.Random()
print file[int(rand.random() * len(file))],
Run Code Online (Sandbox Code Playgroud)
dcr*_*sta 17
随机模块定义了choice(),它可以满足您的需求:
import random
words = [line.strip() for line in open('/etc/dictionaries-common/words')]
print(random.choice(words))
Run Code Online (Sandbox Code Playgroud)
另请注意,这假设每个单词本身都在文件的一行中.如果文件非常大,或者经常执行此操作,您可能会发现不断重读文件会对应用程序的性能产生负面影响.
另一种解决方案是使用getline
import linecache
import random
line_number = random.randint(0, total_num_lines)
linecache.getline('/etc/dictionaries-common/words', line_number)
Run Code Online (Sandbox Code Playgroud)
从文档:
linecache模块允许从任何文件获取任何行,同时尝试使用缓存在内部进行优化,这是从单个文件中读取许多行的常见情况
编辑:您可以计算一次总数并存储它,因为字典文件不太可能改变.
>>> import random
>>> random.choice(list(open('/etc/dictionaries-common/words')))
'jaundiced\n'
Run Code Online (Sandbox Code Playgroud)
这是有效的人类时间.
顺便说一句,你的实现与stdlib的实现一致random.py:
def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
return seq[int(self.random() * len(seq))]
Run Code Online (Sandbox Code Playgroud)
我想知道所提出的解决方案的相对性能是什么.linecache基于明显的最爱.random.choice与实施的诚实算法相比,单线程的速度要慢多少select_random_line()?
# nadia_known_num_lines 9.6e-06 seconds 1.00
# nadia 0.056 seconds 5843.51
# jfs 0.062 seconds 1.10
# dcrosta_no_strip 0.091 seconds 1.48
# dcrosta 0.13 seconds 1.41
# mark_ransom_no_strip 0.66 seconds 5.10
# mark_ransom_choose_from 0.67 seconds 1.02
# mark_ransom 0.69 seconds 1.04
Run Code Online (Sandbox Code Playgroud)
(每个函数调用10次(缓存性能)).
这些结果表明,简单的解决方案(dcrosta)在这种情况下比一个更有意思的一个(mark_ransom)更快.
import linecache
import random
from timeit import default_timer
WORDS_FILENAME = "/etc/dictionaries-common/words"
def measure(func):
measure.func_to_measure.append(func)
return func
measure.func_to_measure = []
@measure
def dcrosta():
words = [line.strip() for line in open(WORDS_FILENAME)]
return random.choice(words)
@measure
def dcrosta_no_strip():
words = [line for line in open(WORDS_FILENAME)]
return random.choice(words)
def select_random_line(filename):
selection = None
count = 0
for line in file(filename, "r"):
if random.randint(0, count) == 0:
selection = line.strip()
count = count + 1
return selection
@measure
def mark_ransom():
return select_random_line(WORDS_FILENAME)
def select_random_line_no_strip(filename):
selection = None
count = 0
for line in file(filename, "r"):
if random.randint(0, count) == 0:
selection = line
count = count + 1
return selection
@measure
def mark_ransom_no_strip():
return select_random_line_no_strip(WORDS_FILENAME)
def choose_from(iterable):
"""Choose a random element from a finite `iterable`.
If `iterable` is a sequence then use `random.choice()` for efficiency.
Return tuple (random element, total number of elements)
"""
selection, i = None, None
for i, item in enumerate(iterable):
if random.randint(0, i) == 0:
selection = item
return selection, (i+1 if i is not None else 0)
@measure
def mark_ransom_choose_from():
return choose_from(open(WORDS_FILENAME))
@measure
def nadia():
global total_num_lines
total_num_lines = sum(1 for _ in open(WORDS_FILENAME))
line_number = random.randint(0, total_num_lines)
return linecache.getline(WORDS_FILENAME, line_number)
@measure
def nadia_known_num_lines():
line_number = random.randint(0, total_num_lines)
return linecache.getline(WORDS_FILENAME, line_number)
@measure
def jfs():
return random.choice(list(open(WORDS_FILENAME)))
def timef(func, number=1000, timer=default_timer):
"""Return number of seconds it takes to execute `func()`."""
start = timer()
for _ in range(number):
func()
return (timer() - start) / number
def main():
# measure time
times = dict((f.__name__, timef(f, number=10))
for f in measure.func_to_measure)
# print from fastest to slowest
maxname_len = max(map(len, times))
last = None
for name in sorted(times, key=times.__getitem__):
print "%s %4.2g seconds %.2f" % (name.ljust(maxname_len), times[name],
last and times[name] / last or 1)
last = times[name]
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14747 次 |
| 最近记录: |