列表

时间:2015-09-24 14:42:51

标签: python

我的问题的概念是识别随机数字母。

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

3 个答案:

答案 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