3

I have two lists: ra_list, e_list.

ra_list is a list of random numbers, e_list is a list with tuples consisting on a number and a categorisation.

A number from ra_list is compared to the number in e_list, and its category is given, as follows:

ra_list = [5,5,6,7,7]
e_list = [(7, A), (7, B), (6, C), (5,D)]

for x in ra_list:
     val = None
     for i in xrange(0,len(e_list)-1):


            if x[1] >= e_list[i][1] and x[1] < e_list[i+1][1]:
                 val = e_list[i][0]


            if val == None:
                 val = e_list[-1][0]


     print x, val 

The current output looks like: 5 D, 5 D, 6 C, 7 B, 7 B

This runs partially fine, however when I have two numbers within two tuples with diferente categorisations only one is considered and selected as result (e.g. the program states that a 7 from ra_list is always B, but, as you can see, A is also 7)

Is it possible to implement a list within a list that will randomise between A and B? Or if there was another categorisation with the same number, e.g. if A and B were 7 and C and D were 6, it'd randomly pick A or B and C or D. I know that I can randomise through a list with:

    random.choice(list_of_duplicates)

But I'm struggling on how to create the list of duplicates and join it with the original list.

If anyone has a suggestion or can point me in the right direction I'd appreciate it. Thank you!

EDIT

What it ra_list are floats, and thus in the range between element 1 and element 2? e.g.

    ra_list = [7.53, 3.42, 35.64]
    e_lst = [(a, 7), (b, 7), (c,8), (d,23)]

Output would be 7.53 a or b as its in the range between a,b and c.

4 Answers 4

4

Using list comprehension and random choice

Code:

ra_list = [5,5,6,7,7]
e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]


import random

for element in ra_list:
    print random.choice([value for value in e_list if element == value[0]])

(5, 'D')
(5, 'D')
(6, 'C')
(7, 'B')
(7, 'A')

Code1:

import random

ra_list = [5,5,6,7,7]
e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]

for element in ra_list:
    print element,random.choice([value[1] for value in e_list if element == value[0]])

output:

5 D
5 D
6 C
7 A
7 B

Code2:

ra_list = [7.84, 8.09, 7.40] 
e_list= [('a', 7.31), ('b', 7.31), ('c', 8.08),('d',7.84)]
import random

for element in ra_list:
    check_list=[value for value in e_list if element == value[1]]
    if len(check_list)>0:
        print random.choice(check_list)
    else:
        print element,"No-match"

Output:

('d', 7.84)
8.09 No-match
7.4 No-match

Code3:

ra_list = [7.53, 3.42, 35.64]
e_lst = [('a', 7), ('b', 7), ('c',8), ('d',23)]

import random
for element in ra_list:
    check_list=[value for value in e_lst if round(element) == value[1]]
    if len(check_list)>0:
        print random.choice(check_list)
    else:
        print element,"No-match"

Output:

('c', 8)
3.42 No-match
35.64 No-match
Sign up to request clarification or add additional context in comments.

11 Comments

@user47467 can you show the full traceback I think there are some element in e_list with one value
@VigneshKalai Check my answer for finding the reason!
print element, random.choice([value[1] for value in e_list if element == value[0]]) File "C:\Python27\lib\random.py", line 274, in choice return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty IndexError: list index out of range
@user47467 you have a value in ra_list which is not available in e_list
@user47467 could you provide values of both lists
|
2

First you can use a dictionary to preserve the numbers as a key and the corresponding characters in a list as values the use a function with yield to return a generator based on your condition :

>>> def printer(ra,e_list.d={}):
...     for i,j in e_list:
...       d.setdefault(i,[]).append(j)
...     for i in ra:
...         val=d.get(i)
...         if len(val)==1:
...              yield i,val[0]
...         else :
...              yield i,random.choice(val)

Demo :

>>> import random
>>> list(printer(ra_list,e_list))
[(5, 'D'), (5, 'D'), (6, 'C'), (7, 'B'), (7, 'B')]
>>> list(printer(ra_list,e_list))
[(5, 'D'), (5, 'D'), (6, 'C'), (7, 'B'), (7, 'A')]
>>> 

Note that based on following benchmark this recipe would be pretty much faster on greater lists than @Vignesh Kalai's answer that called the random function on each list and used a nested for loop :

from timeit import timeit

s1="""
ra_list = [5,5,6,7,7]*100
e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]


for element in ra_list:
    random.choice([value for value in e_list if element == value[0]])


"""

s2="""
ra_list = [5,5,6,7,7]*100
e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]

def printer(ra,e_list,d={}):
     for i,j in e_list:
       d.setdefault(i,[]).append(j)
     for i in ra:
         val=d.get(i)
         if len(val)==1:
              yield i,val[0]
         else :
              yield i,random.choice(val)

list(printer(ra_list,e_list))

   """


print '1st: ' ,timeit(stmt=s1, number=1000,setup='import random')
print '2nd : ',timeit(stmt=s2, number=1000,setup="import random")

result :

1st:  3.390841960907
2nd :  1.092016124725

3 Comments

too much mate :p and by the way are you the downvoter
@VigneshKalai Yes I was. :-)
downvoting just because the run time of answer was slow I think it is too harsh :P. Then you have to go on downvote many answer in SO:p
1

If you want to randomly select , it would be easier to create a dictionary of the values:category , where category would be a list of categories , and then you can use random.choice() on that list.

For this you can use dict.setdefault with the default value as an empty list [] , this function sets the default value to key if it does not exist, otherwise it returns the value for the key passed to it.

Example -

ra_list = [5,5,6,7,7]
e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]

cate_dict = {}

#Creating dictionary of categories
for key,val in e_list:
    cate_dict.setdefault(key,[]).append(val)

import random
for i in ra_list:
    cate = random.choice(cate_dict.get(i,[0])) #To handle cases where `i` does not have category, if this is not the case then you do not need the second argument to `.get`. Use something other than `0` if that is one of the categories.
    if cate != 0:  #To handle cases where `cate` is someother value that can be false in boolean context.
        print i,cate

Demo -

>>> ra_list = [5,5,6,7,7]
>>> e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]
>>>
>>> cate_dict = {}
>>>
>>> #Creating dictionary of categories
... for key,val in e_list:
...     cate_dict.setdefault(key,[]).append(val)
...
>>> import random
>>> for i in ra_list:
...     cate = random.choice(cate_dict.get(i,[0]))
...     if cate != 0:
...             print(i,cate)
...
5 D
5 D
6 C
7 B
7 A

13 Comments

I get a list index out of range error for your code
Exactly where do you get that?
cate = random.choice(cate_dict.get(i,[]))
Try the latest 0 version - cate = random.choice(cate_dict.get(i,[0])) . But still you should not get index out of range there. Hmm
runs but doesn't print
|
1

You can create a dictionary of duplicates rater then creating a list of lists. Dict will be cleaner.

e_list = [(7, 'A'), (7, 'B'), (6, 'C'), (5,'D')]

from collections import defaultdict

res_dict = defaultdict(list)

for item in e_list:
    res_dict[item[0]].append(item[1])

print res_dict #defaultdict(<type 'list'>, {5: ['D'], 6: ['C'], 7: ['A', 'B']})

Now you can go ahead and add your logic to get the desired output.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.