0

I was wondering if there's a way in Python to get from a list, a random value of it and its position at the same time.

I know I can do this in two steps:

list_index = random.randrange(len(my_list))
list_value = my_list[index]

Also I want to exclude if there's a 0 value inside the list. I can't use random() 1st for getting a position because this way I need to recursively call random() until I don't get a 0.

Another posibility is to call random() to get values inside the list and exclude the 0, but with this implementation if, for example, there're two (or more) indentical values, Python outputs me the 1st position:

Example:

    [3 5 6 8 5 0]
    Random's output value = 5
    Position = 1

    But 5 value is also in position 4

How can I implement this? Is it feasible? I've been thinking and searching on the web so much, but couldn't find anything.

Really thank you in advance.

Alex

  • If you're willing to use libraries, `numpy.argwhere(my_list == 5)` would work...https://numpy.org/doc/stable/reference/generated/numpy.argwhere.html – chappers Sep 13 '20 at 11:51
  • 1
    `Python outputs me the 1st position`: well this time was the first position but since it's random it will not always be the case. Not sure to understand your issue. – Corentin Pane Sep 13 '20 at 11:51
  • Because for me position is also mandatory when I get a random value inside the list, I need the value and the position for later. – Alejandro R. Sep 13 '20 at 12:16
  • When calling list_index = random.randrange(len(my_list)) you get the full range of possible indexes. Not only the 1st position of a value. This first position you get if you use my_list.index() e.g. my_list.index(5) -> 1. – Mace Sep 13 '20 at 12:19
  • That's true but If I want to exclude 0 from possible values to get from the list as I'm getting position first i need to check if it's 0 later and then call random again recursively – Alejandro R. Sep 13 '20 at 12:23
  • I wasn't very clear with my words. I changed the question so I think is clear already – Alejandro R. Sep 13 '20 at 12:26
  • I don't see the need for recursion in your question. I have added an answer. Let us know if this gets you started with a solution. – Mace Sep 13 '20 at 12:31

3 Answers3

1

Up to python 3.7 you can use a list of the enumerate()d values of your list - this might break in long lists due to memory consumption:

data = [3, 5, 6, 8, 5, 7]

import random

pos, item = random.choice(list(enumerate(data)))

print("pos:", pos, "itemvalue:", item)

Output:

pos: 2 itemvalue: 6

With python 3.8 you can use the walrus operator which makes it viable for any-lenght lists:

data = [3, 5, 6, 8, 5, 7]

import random 
print("pos:", p := random.choice(range(len(data))), "itemvalue:", data[p]) 

Output:

pos: 0 itemvalue: 3

The 1st variant chooses from tuples that contains the position and the value - the 2nd variant chooses a random index into the list and acceses the liston that position to get the value.


You get random values from your input list - to avoid zeros you can loop until you get a non-zero value:

data = [0, 0, 5, 0, 0, 5, 0, 0, 5]

import random

for _ in range(10):
    item = 0
    while item == 0:
        pos, item = random.choice(list(enumerate(data)))
        # pos, item = (p := random.choice(range(len(data))), data[p]) 
    print("pos:", pos, "itemvalue:", item)

Output:

pos: 8 itemvalue: 5     
pos: 8 itemvalue: 5
pos: 5 itemvalue: 5
pos: 8 itemvalue: 5
pos: 2 itemvalue: 5
pos: 5 itemvalue: 5
pos: 2 itemvalue: 5
pos: 8 itemvalue: 5
pos: 5 itemvalue: 5
pos: 8 itemvalue: 5
Patrick Artner
  • 43,256
  • 8
  • 36
  • 57
  • Thank you so much for your quick reply Patrick! The problem is I want to exclude if there's a 0 value inside the list and your way is also somehow getting random the position, right? – Alejandro R. Sep 13 '20 at 12:09
  • @AlejandroR The "I want to ignore 0 values" came as afterthought ... if you do not want to get 0 values but still have the old "positioning" use a while loop around the part where you get the random value: `item = 0` - `while item == 0:` - `pos, item = random.choice(list(enumerate(data)))`. If you want the values repositioned, simply cull all 0 from your input list: `data = [d for d in data if d]`. My code gives a random value from your list and its position in the list - if you have the same value multiple times you get the exact position of the one choosen. – Patrick Artner Sep 14 '20 at 05:32
1

Your question is not very clear to me but as I understand it your idea should be oké and should work fine.

You get the first 5's index when calling my_list.index(5). But you don't use this.

You get a random index and the value at this index which can also be the second 5.

import random

my_list = [3, 5, 6, 0, 8, 5, 7,]

# example of using index()
print(f"This is the first 5's index {my_list.index(5)}")
print()

for i in range(10):

    random_index = random.randrange(len(my_list))
    value = my_list[random_index]
    if value > 0:
        print(f'At position {random_index} the number is {value}')
    else:
        print(f'     Skipping position {random_index} the number is ZERO!')

Result

This is the first 5's index 1

At position 6 the number is 7
At position 6 the number is 7
At position 0 the number is 3
     Skipping position 3 the number is ZERO!
At position 4 the number is 8
At position 1 the number is 5
At position 5 the number is 5
At position 1 the number is 5
At position 1 the number is 5
At position 4 the number is 8

As you can see your method gets index 1 as well as index 5 for the number 5 in the list.

Mace
  • 1,140
  • 6
  • 11
0

Well, you can use filter function for doing that you want.

res_list = list(filter(lambda x: my_list[x] == random_value, range(len(my_list)))) 

The code above, res_list stores a list which contains indices.

ZaO Lover
  • 449
  • 1
  • 12