我的问题的概念是识别随机数字母。
ra_list
保存随机浮点数。
e_list
持有字母和范围。
当前代码识别字符串匹配和B和C字母之间的随机化,因为它们具有相同的值。
ra_list = [6, 7, 7]
e_list = [(6, 'A'), (7, 'B'), (7, 'C'), (8, 'E')]
test_dict = {}
for key,val in e_list:
test_dict.setdefault(key,[]).append(val)
import random
for i in ra_list:
cate = random.choice(test_dict.get(i,[0]))
if cate != 0:
print i,cate
但是,我的问题是我在ra_list
中有浮点数并希望实现范围 - 我的python经验非常少。如何操纵当前代码并解决范围内的问题? e_list
将始终按升序排列。例如:
ra_list = [6.25, 7.5, 7.6]
e_list = [(6, 'A'), (7.4, 'B'), (7.4, 'C'), (7.7, 'E')]
output = (6.25, A), (7.5, B or C), (7.6, B or C)
ra_list
小于e_list
第一个值的值应为A
,值大于最后一个值的值应为E
。
答案 0 :(得分:1)
一种天真的方法是创建一个字典键的排序列表,并找到一个具有最大值但又小于输入浮点值的字典键。
from collections import OrderedDict
import random
ra_list = [5, 6.25, 7.5, 7.6]
e_list = [(6, 'A'), (7.4, 'B'), (7.4, 'C'), (7.7, 'E')]
test_dict = OrderedDict()
for key,val in e_list:
test_dict.setdefault(key,[]).append(val)
key_list = list(test_dict.keys())
min_key = key_list[0]
for i in ra_list:
max_key = min_key
for key in key_list:
if i >= key:
max_key = key
else:
break
cate = random.choice(test_dict.get(max_key))
print( i,cate)
这比将输入float转换为整数更复杂,但是有一个好处就是可以向你的(数字,字母)对添加浮点数。
编辑2: 根据评论更新了原始答案。
答案 1 :(得分:0)
您可以执行以下操作:
In [1]: e_list = [(6, 'A'), (7, 'B'), (7, 'C'), (8, 'E')]
In [2]: import random
In [3]: from collections import OrderedDict
In [4]: choices_dict = OrderedDict()
In [5]: for x in e_list:
ra = x[0]
e = x[1]
if ra in choices_dict:
choices_dict[ra].append(e)
else:
choices_dict[ra] = [e]
In [6]: choices_dict
Out [6]: OrderedDict([(6, ['A']), (7, ['B', 'C']), (8, ['E'])])
choices_dict
是一个包含限制和字母的字典。
我们创建一个函数get_e_value
,它会为给定的e
提供ra
的值。
如果值位于范围内,则从choices_dict
返回从下限开始的字母列表中的随机字母。否则,返回最高范围的信件。
In [7]: def get_e_value(my_number):
limits = choices_dict.keys()
limits_count = len(limits)
for x in range(limits_count):
if (my_number <= limits[x]) or (x!= limits_count-1 and my_number<limits[x+1]): # check if number lies between a range
choices = choices_dict[limits[x]]
return random.choice(choices)
last_key = limits[-1] # number is beyond range
return random.choice(choices_dict[last_key]) # return largest range letter
In [8]: ra_list = [1.3, 2.5, 5, 6.3, 7.5, 8.5]
In [9]: final_output = [(x, get_e_value(x)) for x in ra_list]
In [10]: final_output
Out [10]: [(1.3, 'A'), (2.5, 'A'), (5, 'A'), (6.3, 'A'), (7.5, 'C'), (8.5, 'E')]
答案 2 :(得分:0)
您可以使用bisect模块使用每个子元组中的第一个元素作为切分的键,这将为您提供O(N log N)
的运行时间,而不是二次方:
from bisect import bisect
from random import choice
def pair(l, l2):
# use first element from each tuple as the key
keys = [r[0] for r in l2]
for i in l:
# find the index i would go in keys to keep order
ind = bisect(keys, i)
# make sure we don't wrap araound i.e 0 to -1
# and don't fall of the end
ind = ind - 1 if ind > 0 else ind
yield (i, e_list[ind][1])
输出:
In [32]: ra_list = [5.5, 6.25, 7.5, 7.6, 7.7,9.0]
In [33]: e_list = [(6, 'A'), (7.4, 'B'), (7.4, 'C'), (7.7, 'E')]
In [34]: list(pair(ra_list, e_list))
Out[34]: [(5.5, 'A'), (6.25, 'A'), (7.5, 'C'), (7.6, 'C'), (7.7, 'E'), (9.0, 'E')]
如果你真的想要一个随机选择重复值,逻辑是完全相同的,你只需要再次在dict中对它们进行分组,并检查每个相应键的值/列表的长度是否包含多个元素与否,如果它随机选择一个:
def pair(l, l2):
dct = {}
for a, b in l2:
dct.setdefault(a, []).append(b)
keys = [r[0] for r in l2]
for i in l:
ind = bisect(keys, i)
print(ind,i)
ind = ind - 1 if 0 < ind else ind
val = dct[e_list[ind][0]]
yield ((i, val[0]) if len(val) == 1 else (i, choice(val)))
输出:
In [63]: ra_list = [5.5, 6.25, 7.5, 7.6, 7.7, 7.8, 9.0]
In [64]: e_list = [(6, 'A'), (7.4, 'B'), (7.4, 'C'), (7.7, 'E'), (7.7, "F")]
In [65]: print(list(pair(ra_list, e_list)))
[(5.5, 'A'), (6.25, 'A'), (7.5, 'C'), (7.6, 'C'), (7.7, 'F'), (7.8, 'F'), (9.0, 'E')]
In [66]: print(list(pair(ra_list, e_list)))
[(5.5, 'A'), (6.25, 'A'), (7.5, 'B'), (7.6, 'C'), (7.7, 'F'), (7.8, 'F'), (9.0, 'E')]
In [67]: print(list(pair(ra_list, e_list)))
[(5.5, 'A'), (6.25, 'A'), (7.5, 'B'), (7.6, 'B'), (7.7, 'F'), (7.8, 'F'), (9.0, 'F')]
In [68]: print(list(pair(ra_list, e_list)))
[(5.5, 'A'), (6.25, 'A'), (7.5, 'C'), (7.6, 'B'), (7.7, 'F'), (7.8, 'F'), (9.0, 'E')]
In [69]: print(list(pair(ra_list, e_list)))
[(5.5, 'A'), (6.25, 'A'), (7.5, 'C'), (7.6, 'C'), (7.7, 'E'), (7.8, 'F'), (9.0, 'E')]
不确定是否会出现完全匹配的情况,如果它与上面的7.7
一样,它会使用相应的值,如果它应该是其他的话那么它仍然只会持续工作,所以运行时将保持不变在N log N