以下是用于优化的代码:
import random
rules = {
'X': {
1: 'FXFF+',
2: '+XXF]',
}
}
L_string = 'FX'
def next_char(c):
isrule = rules.get(c, c)
if not isrule == c:
_, choice = random.choice(list(rules.get(c).items()))
return choice
else:
return isrule
for _ in range(6):
L_string = ''.join([next_char(c) for c in L_string])
这里发生的是递归替换字符串中的字符。所以一步一步来:
最后,结果是一个较长的字符串,该字符串由开头的“ F”和规则“ FXFF +”,“ + XXF]”以某种随机组合组成。该表说明:
+------------+--------------------+--------------------+
| ITERATIONS | STRING | CHOSEN RULE VECTOR |
+------------+--------------------+--------------------+
| 1 | FFXFF+ | [rule 1] |
| 2 | FF+XXF]FF+ | [rule 2] |
| 3 | FF+FXFF++XXF]F]FF+ | [rule 1, rule 2] |
| 4 | ... | ... |
| 5 | ... | ... |
+------------+--------------------+--------------------+
我读到re.sub是替换字符串最快的方法,但问题是每个字符的随机性。 Re.sub对此不起作用。
谢谢!
答案 0 :(得分:2)
一个简单的〜4倍速度加快了消耗大部分运行时间的功能。
"$i"
优化的空间可能很大。也许某个地方的备忘通常可以为整个代码带来巨大的推动。
答案 1 :(得分:2)
假设字符“ {”和“}”未出现在模式中,则可以使用模板语言进行一些欺骗,然后再去除花括号。这在我的机器上快了2.5倍:
mydomains = []
with open("domains.txt") as f:
for line in f:
mydomains.append(line)
for item in mydomains:
params = {
'query': item,
'no.com', # string for get info
'se': 'g_it', # string search engine
'token': 'ad868fb77d43cfa57bc', # string personal token
}
答案 2 :(得分:1)
具有递归的新方法,速度大约快1.6倍,另一种方法,在我的PC上速度快大约3.312倍
import re
from random import random, choice
from timeit import timeit
from math import floor
# --- ORIGINAL ---
rules = {
'X': {
1: 'FXFF+',
2: '+XXF]',
}
}
def next_char(c):
isrule = rules.get(c, c)
if not isrule == c:
_, _choice = choice(list(rules.get(c).items()))
return _choice
else:
return isrule
# --- ORIGINAL END ---
def next_char2(c):
if c not in rules:
return c
d = rules[c]
r = floor(random() * len(d)) # was int(...) before
# Rules start with key 1.
# Random brings a float between 0 and 1, therefore you need [r + 1] as key
return d[r + 1]
choices=['FXFF+', '+XXF]']
def next_substring(s, n):
if s == '' or n == 0:
return s
first_char = s[:1]
rest = s[1:]
if first_char == 'X':
first_char = choice(choices)
if len(first_char) == 1:
return first_char + (next_substring(rest, n) if 'X' in rest else rest)
else:
return (next_substring(first_char, n-1) if 'X' in first_char else first_char) + (next_substring(rest, n) if 'X' in rest else rest)
format_rules = {
'X': lambda: choice(["{F}{X}{F}{F}+", "+{X}{X}{F}]"]),
'F': lambda: 'F',
'J': lambda: 'J',
}
def format_based():
def get_callbacks():
while True:
yield {k: v() for k, v in format_rules.items()}
callbacks = get_callbacks()
L_string = "{F}{X}"
for _ in range(6):
L_string = L_string.format(**next(callbacks))
return re.sub(r'{|}', '', L_string)
def method1():
s = 0
for i in range(100_000):
L_string = 'FX'
for _ in range(6):
L_string = ''.join([next_char(c) for c in L_string])
s += len(L_string)
return s
def method1b():
s = 0
for i in range(100_000):
L_string = 'FX'
for _ in range(6):
L_string = ''.join([next_char2(c) for c in L_string])
s += len(L_string)
return s
def method2():
s = 0
for i in range(100_000):
L_string = 'FX'
L_string = ''.join(next_substring(c, 6) if c=='X' else c for c in L_string)
s += len(L_string)
return s
def method3():
s = 0
for i in range(100_000):
L_string = format_based()
s += len(L_string)
return s
rules2 = [
('FXFF+', '+XXF]') # X=0
]
def new_method2(s='FX'):
final = [s]
s = ''
for _ in range(6):
for c in final[-1]:
if c == 'X':
s += rules2[0][floor(random() * len(rules2[0]))] # rules2[0] because X=0
else:
s += c
final.append(s)
s = ''
return final[-1]
def method4():
s = 0
for i in range(100_000):
L_string = new_method2('FX')
s += len(L_string)
return s
print('Average length of result string (100_000 runs):')
print('{: <20}{: >20}'.format('Original:', method1() / 100_000))
print('{: <20}{: >20}'.format('New method:', method2() / 100_000 ))
print('{: <20}{: >20}'.format('@hilberts method:', method3() / 100_000 ))
print('{: <20}{: >20}'.format('new_method2 method:', method4() / 100_000 ))
print('{: <20}{: >20}'.format('altunyurt method:', method1b() / 100_000 ))
print('{: <20}{: >20}'.format('Timing original:', timeit(lambda: method1(), number=1)))
print('{: <20}{: >20}'.format('Timing new method:', timeit(lambda: method2(), number=1)))
print('{: <20}{: >20}'.format('Timing @hilberts method:', timeit(lambda: method3(), number=1)))
print('{: <20}{: >20}'.format('new_method2 method:', timeit(lambda: method4(), number=1)))
print('{: <20}{: >20}'.format('altunyurt method:', timeit(lambda: method1b(), number=1)))
结果:
Average length of result string (100_000 runs):
Original: 85.17692
New method: 85.29112
@hilberts method: 85.20096
new_method2 method: 84.88892
altunyurt method: 85.07668
Timing original: 4.563865200005239
Timing new method: 2.6940059370026574
Timing @hilberts method: 1.9866539289942011
new_method2 method: 1.3680451929976698
altunyurt method: 1.7981422250013566
编辑:添加了@hilberts方法
EDIT2:添加了另一种新方法,比原始方法快约3.32倍
EDIT3:添加了@altunyurt方法
答案 3 :(得分:0)
您可以尝试使用具有替换值的re.sub
作为根据您的情况生成随机规则的函数。您可以将字符串写入磁盘中的文件,然后
set buffering
读取文件,然后将替换值写入另一个文件,然后重命名该文件并删除旧文件。希望这会有所帮助:)。
import re
import random
rules = {
'X': ['FXFF+','+XXF]'],
"Y" : ['A','B']
}
L_string = 'FX'
def next_char(c):
return random.choice(rules[c.group()])
for _ in range(6):
L_string = re.sub('|'.join(rules.keys()),next_char,L_string)
print(L_string)
输出
FFXFF+
FFFXFF+FF+
FFF+XXF]FF+FF+
FFF++XXF]+XXF]F]FF+FF+
FFF+++XXF]FXFF+F]+FXFF+FXFF+F]F]FF+FF+
FFF++++XXF]FXFF+F]FFXFF+FF+F]+F+XXF]FF+F+XXF]FF+F]F]FF+FF+
已编辑
我进行了编辑,以使其速度更快并通过递归调用生成最后一个字符串。请原谅我使用全局变量:P。
import re
import random
rules = {
'X': ['XX','XY'],
'Y' : ['A', 'B']
}
L_string = 'FXY'
depth = 6
result = ''
index = 0
def go(d,currentstring) :
global result,depth
if (d < depth):
for c in currentstring:
if c in rules:
go(d + 1,random.choice(rules[c]))
else:
result += c
else:
result += currentstring
go(0,L_string)
print(result)
答案 4 :(得分:0)
这将生成无替换的输出:
document.getElementsByTagName('body')[0].onclick = function(e) {console.log(e.target.id)};