user47467
user47467

Reputation: 1093

Python list within list

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.

Upvotes: 3

Views: 720

Answers (4)

The6thSense
The6thSense

Reputation: 8335

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

Upvotes: 4

Anand S Kumar
Anand S Kumar

Reputation: 91007

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

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107357

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

Upvotes: 2

Barun Sharma
Barun Sharma

Reputation: 1468

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.

Upvotes: 1

Related Questions