Python3 faire un random mais avoir au moins 1 fois tous les élements

a marqué ce sujet comme résolu.

Bonjour, petite question, j’ai actuellement un programme qui fait des mélanges d’échantillon au hasard Il me génère des tuples des index de ces éléments

1
2
3
4
5
6
7
        donnees=[["chaud","froid","moyen"],["rouge","bleu","vert","violet","noir","blanc"],["epais","fin"]]
        echantillon_list=[]
        for i in range(100):
            echantillon=tuple(random.choice(range(len(feature))) for feature in donnees)
            echantillon_list.append(echantillon)

        print(echantillon_list)

mon programme fonctionne très bien à un détail près, il est possible que par exemple l’élément "rouge" n’apparait jamais donc je voudrais que ma liste de tuple echantillon_list possede au moins 1 fois tous tous les éléments de données.

Attention, je ne veut pas avoir toute les combinaisons possible de ces éléments mais juste au moins 1 fois tous les éléments de la liste "données".

je sais pas si c’est très clair ?

+0 -0

Tu peux mélanger toutes les listes et générer un premier jeu de tuples sans choix aléatoire. De cette façon, tu assures que tes éléments apparaissent tous au moins une fois. Ensuite, tu complètes avec ta méthode actuelle.

random.suffle permet de mélanger une liste

+3 -0

Tu peux mélanger toutes les listes et générer un premier jeu de tuples sans choix aléatoire. De cette façon, tu assures que tes éléments apparaissent tous au moins une fois. Ensuite, tu complètes avec ta méthode actuelle.

RomHa Korev

Je dirais même l’inverse. Faire un random pour tirer au hasard les éléments de la liste, PUIS ajouter chaque éléments de bases de la liste et ensuite mélanger tout ça.

Sinon, tu aura forcément les éléments de bases à la suite, sans possibilité d’avoir deux fois de suite le même élément. (Je ne sais pas si je m’exprime très bien).

+1 -0

merci pour vos réponses, mais je vois pas en quoi un shuffle peut m’aider ?

j’ai peut etre mal expliquer ce que fais mon code: il fait des combinaisons de mes échantillons par exemple : "chaud,vert,fin","moyen,bleu,fin" et je voudrais m’assurer que parmi toute les combinaisons existante il existe au moins une combinaison avec "épais", au moins 1 avec "fin", rouge…etc.

+0 -0

Si tu veux du vrai hasard, tu ne peux pas. Ça reviendrait à dire « je veux être sûr de faire au moins un 6 en tirant 10 fois le dé ». Une solution : ne pas faire du vrai hasard. Sois tu le biaises, c’est ce que proposent les solutions au-dessus, soit tu regardes à postériori si la liste crée te convient, et tu recommences si ce n’est pas le cas.

+0 -0

Sinon, tu aura forcément les éléments de bases à la suite, sans possibilité d’avoir deux fois de suite le même élément. (Je ne sais pas si je m’exprime très bien).

FougereBle

Effectivement… Sinon, il faudra refaire un mélange après coup.

Mais voici comment je l’aurais fait (sans les formes, ni l’élégance) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import random

# Liste de base
lists = [["A", "B", "C", "D", "E"], [1, 2], ["foo", "bar", "baz"]]

# Trouver la taille de la liste la plus longue
max_size = len(max(lists, key=len))

# Liste mélangée
shuff_lists = list()

# On commence par construire des listes de même taille
for x in lists:
        # Combien de fois faut-il répéter la liste pour obtenir la taille de la plus longue
        nb_repeat = int(max_size/len(x) + 1)
        # Créer une liste de la bonne taille
        l = (x * nb_repeat)[:max_size]
        print(l)
        # Mélanger
        random.shuffle(l)
        shuff_lists.append(l)

echantillon_list = list()
# Parcourir en générant les tuples
for x, y, z in zip(*shuff_lists):
        echantillon_list.append([x, y, z])

for i in range(10):
        echantillon = list(random.choice(feature) for feature in lists)
        echantillon_list.append(echantillon)

random.shuffle(echantillon_list)

for x in echantillon_list:
        print(" ".join(map(str, x)))

Ton problème n’est pas claire.

Si tu le fais une fois, ben tu auras une combinaison "chaud, vert, épais". Voila.

Pour avoir au moins à chaque fois chacun des termes, il faudrait au moins générer 5 phrases (car il y a 5 couleurs).

Une solution, c’est de prendre le nombre d’élément de la plus grande liste, donc ici 5 pour les couleurs.

Compléter les autres listes avec de la redondance aléatoire par exemple : ["chaud","froid","moyen"]. Au hasard, tu rajoutes ["moyen", "chaud"]. J’ai sélectionné 2 fois un élément aléatoire et du coup de génère la liste suivante : ["chaud","froid","moyen", "moyen", "chaud"]. Je fais pareille pour fin et épais.

Je me retrouve donc avec trois listes :

  • ["chaud","froid","moyen", "moyen", "chaud"]
  • ["rouge","bleu","vert","violet","noir","blanc"]
  • ["épais","fin","fin,"fin","fin","épais"]

Bon, maintenant je shufle un peu le tout :

  • ["froid","chaud","chaud", "moyen", "moyen"]
  • ["rouge","bleu","noir","violet","blanc","vert"]
  • ["fin","fin","fin,"épais","épais","fin"]

Et voilà, du coup, j’ai 5 phrases aléatoires ("froid, rouge, fin", "chaud,bleu,fin", "chaud,noir,fin", "moyen, violet,épais", "moyen,vert,fin") avec au moins chacun des termes utilisé une fois.

Edit: Je suis un peu grillé mais ça m’a pris du temps à écrire tout ça. C’est la même chose que décris dans le code python mais sans code voila.

+0 -0

Je vais proposer une solution inattendue (peut-être celle qu’attend le PO). Sur des petites listes c’est faisables, mais sur des centaines de milliers d’éléments ça risque d’être sportif.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import random

donnees=[["chaud","froid","moyen"],["rouge","bleu","vert","violet","noir","blanc"],["epais","fin"]]

elements = []
for f in donnees:
    for k in f:
        elements.append(k)

print('tous les éléments à utiliser: {}'.format(repr(elements)))
print()

while elements:
    echantillon_list=[]
    for i in range(100):
        elems = []
        for feature in donnees:
            echantillon = random.choice(feature)
            elems.append(echantillon)
            if echantillon in elements:
                elements.remove(echantillon)
        echantillon_list.append(elems)

print(echantillon_list)
print()
print('tous les éléments restants: {}'.format(repr(elements)))

Son objectif était peut-être d’avoir un moyen de vérifier que tous les éléments étaient utilisés en utilisant une méthode par élimination. Sur le principe, c’est une manière pas très optimisée, mais compréhensible quand on débute.

+2 -0

Après réflexion, mon approche n’était pas du tout la bonne et n’intègre pas assez d’aléatoire.

En fait, on cherche simplement à générer aléatoirement une liste en assurant que chaque élément apparaît au moins une fois. Ce qui revient à dire que c’est la liste d’origine complétée de choix aléatoires :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    shuff_lists = list()
    for sub_list in lists:
            l = list()
            # Une liste aléatoire à compléter
            for i in range(10 - len(sub_list)):
                    l.append(random.choice(sub_list))
            # Assure que toutes les valeurs apparaissent au moins une fois
            l += sub_list
            # Insére un peu d'aléatoire dans l'ordre de la liste
            random.shuffle(l)
            shuff_lists.append(l)

    # Génère les tuples
    for x, y, z in zip(*shuff_lists):
            print(x, y, z)
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte