random hasard – Sam & Max http://sametmax.com Du code, du cul Wed, 30 Oct 2019 15:34:04 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Récupérer des éléments d’une liste au hasard avec pondération en python http://sametmax.com/recuperer-des-elements-dune-liste-au-hasard-avec-ponderation-en-python/ http://sametmax.com/recuperer-des-elements-dune-liste-au-hasard-avec-ponderation-en-python/#comments Fri, 07 Sep 2012 12:46:22 +0000 http://sametmax.com/?p=2034 Une méthode qui vaut ce qu’elle vaut mais qui sert pas mal.

Cas de figure, on veut uploader du contenu qui sera mis à disposition d’utilisateurs sur 3 serveurs sur lesquels il ne reste pas la même place…
on peut utiliser une commande ssh pour récupérer la place sur les serveurs par exemple et mettre le résultat dans une liste:

[[place_restante, nom_du_serveur]]

servers = [['10','server1'],['45','server2'],['34','server3']]

La logique voudrait qu’on balance le contenu sur tous les serveurs mais surtout sur le 1 car il a beaucoup de place le salop mais qu’il faut pas tout mettre dessus car on va bouffer toute sa bande passante lors des downloads du contenu alors qu’on a 2 autres serveurs qui branlent rien ou presque…

def w_choice(lst, nb=2):
    """
        weighted choice give it a list as this:
        [[45, 'item1'], [12, 'item2'],[88, 'item3']]
        nb= Number of items to return
    """
    items = []
    w_items = []

    # on récupère tous les serveurs de la liste et leur "poids" (place restante en % par ex)
    for weight, item in lst:
        # on créé une liste dans laquelle on multiplie le nom du serveur par son poids, ex si server1 a 4 de poids on aura 4 éléménts server1
        for x in xrange(100-weight):
            items.append(item)

    # on secoue mais on frappe pas
    random.shuffle(items)

    # on récupère x serveurs sur lesquel on uploadera le contenu
    for item in items:
        if item not in w_items:
            w_items.append(item)
            if len(w_items)==nb:
                break

    return w_items

ci-dessous un petit test pour voir que ça marche:

servers = [['10','server1'],['45','server2'],['34','server3']]

items = {}
for i in xrange(1000):
    lst = w_choice(servers)
    for item in lst:
        items.update({item:items.get(item, 0)+1} )
print items

On obtient:
{'server1': 414, 'server2': 273, 'server3': 313}

Ici server1 sort le plus souvent(414 fois) car la place occupée sur son disque est de 10%, logique qu’on lui envoie plus souvent du contenu histoire de le remplir.

Je ne trouve pas ma fonction spécialement élégante ceci-dit, si certains ont mieux à proposer qu’ils se fassent entendre ;)

]]>
http://sametmax.com/recuperer-des-elements-dune-liste-au-hasard-avec-ponderation-en-python/feed/ 12 2034