White scenery @showyou, hatena

If you have any comments, you may also send twitter @shsub or @showyou.

ランダム並べ替え(重みつき)

[ {'name':'a','count':1}, {'name':'b','count':2}, {'name':'c','count':3} ]という感じに並んでるリストを、数値(a,1の1の方)を重みとしてある程度考慮して並べ替えるアルゴリズムに悩んだ。出てきたものはあっさりしてるけど。

def shuffleByCount(list):

    tmpList = []
    # まず元リストを作る
    for item in list:
        tmpList.append(item)

    result = []
    # 次にリストの中身が空になるまで、GetQueryByCountを実行する
    while tmpList:
        i = GetQueryByCount(tmpList)
        result.append(i)
        tmpList.remove(i)

    print("ok")
    return result

# 数量に応じて結果を返す
# ex: [a:5, b:3, c:2] なら aが5割、bが3割、cが2割の確率
def GetQueryByCount(filter):
    import random
    total = 0
    for q in filter:
        total += q['count']

    t = random.randint(1,total)
    total2 = 0
    for q in filter:
        total2 += q['count']
        if t <= total2:
            result = q
            break
    # ここまででresultにはなにか入ってるはず
    return result

def _test():
    ha = {'name':'a','count':1}
    hb = {'name':'b','count':2}
    hc = {'name':'c','count':3}
    list = [ ha, hb, hc ]

    result = shuffleByCount(list)
    for i in result:
        print( i["name"] )

if __name__ == "__main__":
    _test()

実行結果

$ python shuffleByCount.py
ok
a
b
c
$ python shuffleByCount.py
ok
a
c
b

仮リストにデータ全部入れる→countを全部足す→0〜count-1の値をランダムに取得→そこにある要素を取得→仮リストから削除→またcount全部足す ってやってるけど、選んだ要素の分だけ全部足した奴から引いたほうが速いだろうなぁ。まだ時間が気にならないからいいけど、後で考えておこう。