Pythonのリストからランダムなサブリストを抽出する

2015年11月25日に質問されました。  ·  閲覧回数 13.5k回  ·  ソース

user775093 picture
2015年11月25日

私は次のようなPython辞書を持っています:

{'APPLE_PROVIDERS' : ["some", "provider","can","be", "null"],
  ....
}

私がやりたいのは、キーのリスト(値)からランダムなサブリストを取得することです。 1つの要素だけでなく、完全にランダムなサブリスト。 これが私が試したものです:

a_list = a_dict.get('APPLE_PROVIDERS', "")
for item in a_list[randrange(0,len(a_list)) : randrange(0,len(a_list))]:
  ...do something.. 

これには2つの問題があります:

  1. リストが空の場合、またはdictルックアップが失敗した場合、randrangeの引数が(0,0)であるため、プログラムが失敗し、エラーが発生します。

  2. 多くの場合、特にリストが小さい場合は、両方のrandrange()呼び出しで同じ番号が生成されます。 これにより、空のリストが返されます。 たとえば、a_list [5:5]

では、上記のケースを処理したランダムなサブリストを取得するための最良の方法は何ですか? また、注文は気にしません。 何でも動作します。 forループが開始するたびにlen(a_list)要素まで0,1 ...の完全にランダムなサブリストが必要です。

同様の要素を保持できる他のデータ構造でリストを変更できる場合は、それも機能します。

回答

Ignacio Vazquez-Abrams picture
2015年11月25日
24

それを試してみてください。

>>> random.sample(["some", "provider", "can", "be", "null"], 3)
['some', 'can', 'provider']
>>> random.sample(["some", "provider", "can", "be", "null"], 3)
['can', 'null', 'provider']
>>> random.sample(["some", "provider", "can", "be", "null"], 3)
['null', 'some', 'provider']
John La Rooy picture
2015年11月25日
4
>>> from random import randint
>>> left = randint(0, len(L))
>>> right = randint(left, len(L))
>>> L[left:right]
['null']

空のリストの可能性を望まない場合

>>> left = randint(0, len(L) - 1)
>>> right = randint(left + 1, len(L))
El'endia Starman picture
2015年11月25日
1

イグナシオの答えは素晴らしいです。 コードを最小限に変更したい場合は、次のようにすることができます。

a_list = a_dict.get('APPLE_PROVIDERS', "")
if len(a_list) > 1:
    index1 = randrange(0,len(a_list)-1)
    index2 = randrange(index1+1,len(a_list))
    for item in a_list[index1:index2]:
        pass #do stuff

ここでは2つのことを行います。1)a_listに複数の要素があるかどうかを確認し、2)randrangeを使用してインデックスを生成しますが、2番目が最初よりも大きいことが保証されます。

Games Brainiac picture
2015年11月25日
1

したがって、空のリストを取得した場合に空のリストを返したいと仮定すると、次の解決策があります。

from random import shuffle

def get_random_sublist(the_dict, key, number):
    l = the_dict.get(key, [])
    shuffle(l)
    return l[:number]

したがって、 random.shuffleます。 これにより、取得した実際のリストよりも大きいサブリストを要求する問題を回避できます。

>>> DICT = {'a' : "1 2 3 4 5".split(), 'b': [], 'c': [1]}
>>> get_random_sublist(DICT, 'a', 3)
['4', '1', '2']
>>> get_random_sublist(DICT, 'b', 10)
[]