LoginSignup
0
0

【Python】`random.sample()`と`random.shuffle()`の違いとは?サンプルコードで解説

Posted at

概要

random.sample()random.shuffle()の違いやrandom.choice()の使い方について、サンプルコードを交えて解説します。

サンプルコード

サンプルコードとして、4つの国からなるグループAとグループBを作成し、それぞれのグループからランダムに一つの国を取得して対戦カードを作るコードを実装しました。

import  random


class MatchupGenerator:
    # クラスのコンストラクタ
    def __init__(self, countries):
        self.countries = countries

    # すべてのデータを返す
    def get_all(self):
        return self.countries

    # データをシャッフルしたリストを返す
    def get_shuffle(self):
        return random.sample(self.countries, len(self.countries))

    # ランダムに1つのデータを返す    
    def get_random(self):
        return random.choice(self.countries)

country_group_a = ['Japan', 'Spain', 'Germany', 'Costa Rica']
country_group_b = ['Morocco', 'Croatia', 'Belgium', 'Canada']

group_a_generator = MatchupGenerator(country_group_a)
group_b_generator = MatchupGenerator(country_group_b)


print("All countries in group A:", group_a_generator.get_all())
print("All countries in group B:", group_b_generator.get_shuffle())
print("Random match:", group_a_generator.get_random(), "VS", group_b_generator.get_random())

# 出力結果
# All countries in group A: ['Japan', 'Spain', 'Germany', 'Costa Rica']
# All countries in group B: ['Belgium', 'Canada', 'Croatia', 'Morocco']
# Random match: Japan VS Croatia

(サンプル用にrandomにあるchoicesampleを使うため、GroupBではあえてsampleを使っています)

random.choice()random.randint()

random.choice(self.data)と同じ方法として以下の例もあります。

        idx = random.randint(0, len(self.data) - 1)
        return self.data[idx]

どちらも同じようにランダムな要素を取得する方法です。choiceという便利な方法を知らずに後者の方ではじめ実装していましたが、choiceの方が読みやすく簡潔ですね。

random.choice(self.data):リストからランダムな要素を選択する非常に簡潔な方法
random.randint(0, len(self.data) - 1):インデックスの範囲を指定してランダムなインデックスを生成し、それを使用してリストから要素を取得する方法

random.sample()random.shuffle()

random.sample()と似たものに、random.shuffle()があるのですが、この関数は値を返しません。

そのため、return random.shuffle(self.data)のように直接random.shuffle()return文の中で使用しても、返り値が存在しないためにNoneが返されます。

All countries in group B: None

インプレースで処理されるので、元のデータを新しいものに置き換えたい場合に使います。
ランダムに並び替えられた新しいリストが欲しい場合は、sampleを使う、ということですね。

また、試しにGroupBをタプル(イミュータブルなオブジェクト)に変更すると以下のエラーになります。

    x[i], x[j] = x[j], x[i]
TypeError: 'tuple' object does not support item assignment

これは、random.shuffle()関数は、シーケンス型(リストやタプル)を受け入れますが、シャッフルを行う際に要素の入れ替え(x[i], x[j] = x[j], x[i])を使用しているため、対象となるシーケンスが変更可能(ミュータブル)でなければならないため。タプルは変更不可能(イミュータブル)なのでエラーが出ています。

ちなみに、return random.shuffle(list(self.data))としてリストに変換してあげれば概念的には正しいアプローチですが、この関数自体がNoneを返すため、意味がありません。

公式ドキュメント:

random.choice() --- 擬似乱数を生成する — Python 3.11.3 ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0