【问题标题】:Simple random name generator in PythonPython中的简单随机名称生成器
【发布时间】:2017-11-12 13:56:32
【问题描述】:

我有一个包含第一个和最后一个“音节”的文本文件,用 [part1] 和 [part2] 划分:

[第1部分] 埃 迪 莫 家庭 [第2部分] 达尔 基尔 格拉尔 特雷斯

我要做的就是在 [part1] 和 [part2] 之间选择一条随机线,然后在 [part2] 和文件末尾之间选择另一条随机线,然后将两者连接在一起(例如“Aedar”, "Moglar") 来创建随机名称。

但是我不确定如何使用 readline() 有效地解析文本文件。有没有比顺序扫描每一行更好的方法,并将它们全部存储在一个列表中,我可以从中选择一个随机元素?

【问题讨论】:

  • 文件格式好像是你控制的,不能改成更容易解析的吗?
  • 使用两个文件会容易很多。

标签: python


【解决方案1】:

将字典序列化 (pickle) 改为文件。

例子:

# create the dict and save it to a file
d={
'part1':[
    'Ae',
    'Di',
    'Mo',
    'Fam',],
'part2':[
    'dar',
    'kil',
    'glar',
    'tres',],
}

import pickle
f=open('syllables','w')
pickle.dump(d,f)
f.close()


# read the dict back in from the file
f1=open('syllables','r')
sd=pickle.load(f1)
f1.close()

import random
first_part=sd['part1'][random.randint(0,len(sd['part1'])-1)]
second_part=sd['part2'][random.randint(0,len(sd['part2'])-1)]

print '%s%s'%(first_part,second_part)

【讨论】:

  • sd['part1'][random.randint(0,len(sd['part1'])-1)] ... 或只是random.choice(sd['part1']) 或最后一行print ''.join(random.choice(sd[partName]) for partName in sorted(sd))
  • @eumiro - 是的,在下面看到你的答案,肯定更优雅。干得好!
  • @AJ - 无论如何,您的 dict/pickle 想法比原始文件更好。
  • @eumiro - 谢谢!我绝对更喜欢将文件的创建/维护(管理功能)与其数据的使用(业务/应用程序功能)分开的想法。 pickle 似乎是在这两个用户/角色之间使用的一个非常简单的协议。
  • 我明白,但我希望数据存在于文本文件中——除非我弄错了,我们不是将字典腌制到文件中,然后再次将其作为对象解封吗?有没有办法只在文本文件中声明 d 而不在代码中?
【解决方案2】:
import random
parts = {}

with open('parts.txt', 'r') as f:
    currentList = []
    for line in f.readlines():
        line = line.strip()
        if line.startswith('[') and line.endswith(']'):
            currentList = []
            parts[line[1:-1]] = currentList
        else:
            currentList.append(line.strip())


for i in xrange(10):    
    print ''.join(random.choice(parts[partName]) for partName in sorted(parts))

返回(随机):

Aekil
Didar
Mokil
Mokil
Moglar
Moglar
Diglar
Famdar
Famdar
Modar

【讨论】:

  • 'r' 是默认模式;你可以省略它。 f.readlines() 读取内存中的整个文件;可以改用for line in f:。你可以在一行写currentLIne = parts[line[1:-1]] = []。第一个 currentList(在任何 '[part...]' 行之前)不会添加到任何地方(值被丢弃)。
  • 您可以使用fileinput.input() 而不是硬编码文件名。
  • 这就是我的意思:stackoverflow.com/questions/5731670/…
【解决方案3】:

您必须在某个时候通读整个文件,除非您事先知道有多少前缀和后缀。因为我假设你没有,或者它可以改变并且你不想维护一个数字来存储它,你必须通读文件,而 readline() 是这样做的好方法。

但是,您可以对文本文件进行预处理,使其使用另一种格式,例如 pickle 文件。换句话说,将文本文件读入字典,然后腌制该字典。字典可能看起来像这样:

dic = {'prefixes': ['Ae' ,'di', ...], 'suffixes': ['dar', 'kil', ...]}

根据数组的长度,您可以确定最大随机数是多少。它应该比每次逐行读取整个文件更有效。如果没有,至少它是一个更优雅的解决方案。

【讨论】:

    【解决方案4】:

    修改@eumiro's script

    #!/usr/bin/env python
    import fileinput
    import random
    import re
    from collections import defaultdict
    
    partname = ''
    parts = defaultdict(list)
    for line in fileinput.input():
        line = line.rstrip()
        if line.startswith('[') and re.match(r'\[part\d+\]', line):
            partname = line
        else:
            parts[partname].append(line)
    
    parts_list = list(map(parts.get, sorted(parts)))
    for _ in range(10):
        print(''.join(map(random.choice, parts_list)))
    

    输出

    Famglar
    Famkil
    Didar
    Ditres
    Aedar
    Famglar
    Ditres
    Famtres
    Ditres
    Modar
    

    【讨论】:

      猜你喜欢
      • 2013-01-19
      • 2020-10-16
      • 1970-01-01
      • 1970-01-01
      • 2014-10-16
      • 2018-03-28
      • 2013-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多