RE: random choice from dictionary

2018-12-23 Thread Avi Gross
I did say some would use enumerate but I was rushing to go to my nephews 
wedding and my enum became emum which is meaningless 

If the goal is to make a relatively efficient algorithm and the index made by 
enumerate is not needed, then I judged that the overhead of enumerate(data) 
returning two values to be unpacked each time through the loop might be more 
than having a single counter. Of course enumerate likely is considered more 
pythonic 

Similarly, the suggestion to use islice (although the name is also 
unfortunately reminiscent of is lice) may be a good one. But it basically does 
what my function did, perhaps as fast and perhaps not. My impression is it 
iterates using next() a number of times then stops. It is so simple, there 
might be no need for my function. The request was to find an nth item and you 
can feed (the random) n directly into islice.

Just for amusement, I already get a random word a day in my email from two 
dictionary sources in English as well as quite a few in other languages. I not 
only get the word as a key, but also a translation and even an example sentence 
with translation.

But I doubt the words are chosen randomly and they are not likely to be from a 
python dictionary.

-Original Message-
From: Python-list  On 
Behalf Of MRAB
Sent: Sunday, December 23, 2018 4:21 PM
To: python-list@python.org
Subject: Re: random choice from dictionary

On 2018-12-23 19:52, Avi Gross wrote:
> There are quite a few places the new pythonic way of doing things 
> requires extra steps to get an iterator to expand into a list so 
> Abdul-Rahmann probably is right that there is no easy way to get a 
> random key from a standard dictionary. Other than the expected answers 
> to make a customized dictionary or function that provides the 
> functionality at the expense for potentially generating a huge list of 
> keys in memory, I offer the following as an alternative for large 
> dictionaries and especially if they have large keys.
> 
> The following is a function that iterates over the dictionary one key 
> at a time and when it reaches a random one, it returns the key without 
> further evaluation. On the average, it takes N/2 iterations for N 
> keys. Asking to make a list(data) may be efficient in terms of time 
> and indexing is fast but space is used maximally unless it just points to 
> existing storage.
> 
> Here is one way to do the function. Some might use an emum instead.
> 
> def rand_key(data):
>  """Get a random key from a dict without using all of memory."""
>  import random
>  randy = random.randrange(len(data))
>  this = 0
>  for key in data:
>  if (this == randy):
>  return(key)
>  this += 1
> 
[snip]
You might as well use 'enumerate' there:

def rand_key(data):
 """Get a random key from a dict without using all of memory."""
 import random
 randy = random.randrange(len(data))
 for this, key in enumerate(data):
 if this == randy:
 return key

Or you could use 'islice':

def rand_key(data):
 """Get a random key from a dict without using all of memory."""
 import itertools
 import random
 randy = random.randrange(len(data))
 return list(itertools.islice(data, randy, randy + 1))[0]
--
https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread sarah123ed



Maybe something like this:

import random
k = list(data.keys())
random.shuffle(k)
result = data[k[0]]



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread sarah123ed


Maybe something like this?

import random
k = list(data.keys())
random.shuffle(k)
selected = f[k[0]]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread Ben Bacarisse
"Avi Gross"  writes:

> The following is a function that iterates over the dictionary one key at a
> time and when it reaches a random one, it returns the key without further
> evaluation. On the average, it takes N/2 iterations for N keys. Asking to
> make a list(data) may be efficient in terms of time and indexing is fast but
> space is used maximally unless it just points to existing storage.
>
> Here is one way to do the function. Some might use an emum instead.
>
> def rand_key(data):
> """Get a random key from a dict without using all of memory."""
> import random
> randy = random.randrange(len(data))
> this = 0
> for key in data:
> if (this == randy):
> return(key)
> this += 1

There is beautiful variation on this that can select k random keys:

def sample_keys(data, k = 1):
"""Return k random keys from a dict."""
import random
items = len(data)
keys = []
for key in data:
r = random.random()
if r < k/items:
keys.append(key)
k -= 1
items -= 1
return keys

And there is a variation on /that/ will use fewer random numbers --
essentially picking a number of "skip" distances as you pick one.  But
it's late, and I need to get ready to eat lots...


-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread MRAB

On 2018-12-23 19:52, Avi Gross wrote:

There are quite a few places the new pythonic way of doing things requires
extra steps to get an iterator to expand into a list so Abdul-Rahmann
probably is right that there is no easy way to get a random key from a
standard dictionary. Other than the expected answers to make a customized
dictionary or function that provides the functionality at the expense for
potentially generating a huge list of keys in memory, I offer the following
as an alternative for large dictionaries and especially if they have large
keys.

The following is a function that iterates over the dictionary one key at a
time and when it reaches a random one, it returns the key without further
evaluation. On the average, it takes N/2 iterations for N keys. Asking to
make a list(data) may be efficient in terms of time and indexing is fast but
space is used maximally unless it just points to existing storage.

Here is one way to do the function. Some might use an emum instead.

def rand_key(data):
 """Get a random key from a dict without using all of memory."""
 import random
 randy = random.randrange(len(data))
 this = 0
 for key in data:
 if (this == randy):
 return(key)
 this += 1


[snip]
You might as well use 'enumerate' there:

def rand_key(data):
"""Get a random key from a dict without using all of memory."""
import random
randy = random.randrange(len(data))
for this, key in enumerate(data):
if this == randy:
return key

Or you could use 'islice':

def rand_key(data):
"""Get a random key from a dict without using all of memory."""
import itertools
import random
randy = random.randrange(len(data))
return list(itertools.islice(data, randy, randy + 1))[0]
--
https://mail.python.org/mailman/listinfo/python-list


RE: random choice from dictionary

2018-12-23 Thread Avi Gross
There are quite a few places the new pythonic way of doing things requires
extra steps to get an iterator to expand into a list so Abdul-Rahmann
probably is right that there is no easy way to get a random key from a
standard dictionary. Other than the expected answers to make a customized
dictionary or function that provides the functionality at the expense for
potentially generating a huge list of keys in memory, I offer the following
as an alternative for large dictionaries and especially if they have large
keys.

The following is a function that iterates over the dictionary one key at a
time and when it reaches a random one, it returns the key without further
evaluation. On the average, it takes N/2 iterations for N keys. Asking to
make a list(data) may be efficient in terms of time and indexing is fast but
space is used maximally unless it just points to existing storage.

Here is one way to do the function. Some might use an emum instead.

def rand_key(data):
"""Get a random key from a dict without using all of memory."""
import random
randy = random.randrange(len(data))
this = 0
for key in data:
if (this == randy):
return(key)
this += 1

Here is a sample showing it running:

>>> import string
   
>>> data= { key : value for (key, value) in zip(string.ascii_uppercase,
string.ascii_lowercase) }
   
>>> data
   
{'A': 'a', 'B': 'b', 'C': 'c', 'D': 'd', 'E': 'e', 'F': 'f', 'G': 'g', 'H':
'h', 'I': 'i', 'J': 'j', 'K': 'k', 'L': 'l', 'M': 'm', 'N': 'n', 'O': 'o',
'P': 'p', 'Q': 'q', 'R': 'r', 'S': 's', 'T': 't', 'U': 'u', 'V': 'v', 'W':
'w', 'X': 'x', 'Y': 'y', 'Z': 'z'}
>>> rand_key(data)
   
'X'
>>> rand_key(data)
   
'P'
>>> rand_key(data)
   
'D'
>>> rand_key(data)
   
'G'
>>> rand_key(data)
   
'H'
>>> data[rand_key(data)]
   
'x'
>>> data[rand_key(data)]
   
'w'
>>> data[rand_key(data)]
   
'n'
>>> data[rand_key(data)]
   
'h'

Of course it depends on what you want to do. If getting random keys
repeatedly, it would be best to do things like make another dictionary with
the new key being integers from 0 to the length and the new values to be the
old keys. You can then look up a random index to get a random key.

>>> dataindex = { index: key for (index, key) in enumerate(data)}
   
>>> dataindex
   
{0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H', 8: 'I', 9:
'J', 10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O', 15: 'P', 16: 'Q', 17: 'R',
18: 'S', 19: 'T', 20: 'U', 21: 'V', 22: 'W', 23: 'X', 24: 'Y', 25: 'Z'}
>>> dataindex[11]
   
'L'
>>> import random
   
>>> dataindex[random.randrange(len(dataindex))]
   
'Y'
>>> dataindex[random.randrange(len(dataindex))]
   
'O'

Again, depending on your needs, some solutions may be worth extra code, some
may not.


-Original Message-
From: Python-list  On
Behalf Of Abdur-Rahmaan Janhangeer
Sent: Sunday, December 23, 2018 1:17 AM
To: Python 
Subject: random choice from dictionary

greetings,

just a check, is this:

random.choice(list(data.keys()))

the only way to get a random key from a dictionary? if not any plan to a
more convenient naming?

yours,

--
Abdur-Rahmaan Janhangeer
http://www.pythonmembers.club | https://github.com/Abdur-rahmaanJ Mauritius


Garanti
sans virus. www.avast.com

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
--
https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread Abdur-Rahmaan Janhangeer
random.choice(list(data)) is great. fine with arbitrary selection.

else, given data.keys(), how do i get the first key?

yours
-- 
Abdur-Rahmaan Janhangeer
http://www.pythonmembers.club | https://github.com/Abdur-rahmaanJ
Mauritius


Garanti
sans virus. www.avast.com

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: random choice from dictionary

2018-12-23 Thread Chris Angelico
On Sun, Dec 23, 2018 at 7:34 PM Abdur-Rahmaan Janhangeer
 wrote:
>
> greetings,
>
> just a check, is this:
>
> random.choice(list(data.keys()))
>
> the only way to get a random key from a dictionary? if not any plan to a
> more convenient naming?

Does it have to be truly random, or are you okay with it being
arbitrary selected? Dictionaries have a popitem method that may be of
value. Otherwise, I would say what you have is fine, save that I'd
just write random.choice(list(data)) instead of using the unnecessary
keys() call.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list