Question créer un tableau de tableaux

Plus d'informations
il y a 1 mois 1 jour - il y a 1 mois 1 jour #33294 par gerome
Réponse de gerome sur le sujet créer un tableau de tableaux
Oh non j'avais tapé un message super long mais tout s'est effacé au moment de l'envoi 

Du coup pour résumer, j'ai anonymisé mon code pour être complètement transparent.

En fait en arrivant à la fin de mon script, je me rends compte que je ne sais pas manipuler les données d'un tableau, ce qui est problématique car $tabClientsRanked et $weeks en sont !

N'hésitez pas à me faire préciser mes propos, j'ai essayé de documenter mon script du mieux possible, mais ce n'est peut-être pas tout à fait compréhensible.

# importer les colonnes Client et Name du fichier liste.csv dans une variable $datas
$datas = Import-Csv -Path "\\chemin\lsite.csv" -Delimiter ";" | Select-Object Client, Name

# connaître le nombre d'occurrences uniques de la colonne Client : on crée une variable $occurrences qui est une collection
$occurrences = $datas | Group-Object -Property Client

# ajouter une colonne vide nommée "Week" à la collection $occurences
$occurencesWithWeeks = $occurrences | Select-Object @{Name='Client' ; Expression={$_.Name}}, Count, @{Name="Week" ; Expression={$null}}<#, Group /Group est optionnel #>

# classer le tableau par ordre alphabétique en fonction de la colonne Name
$tabClientsRanked = $occurencesWithWeeks | Sort-Object -Property @{Expression="Client";Ascending=$true} # ENLEVER le pipe "| Format-Table" si on veut travailler la variable $tabClientsRanked par la suite
$tabClientsRanked
# compter le nombre de serveurs
$numberOfServers = $datas.Length

# compter le nombre de clients
$numberOfClients = $tabClientsRanked.Length

# compter le nombre de serveurs 
$numberOfServers = $datas.Length

# définir le diviseur maximum à 12 car les serveurs doivent être MAJ au maximum toutes les 12 semaines
$maxDivisor = 12

# définir une variable pour savoir combien de serveurs seront mis à jour chaque semaine en moyenne
$averageNumberOfServersPerUpdate = $numberOfServers/$maxDivisor

# définir une alerte si le nombre de serveurs divisé par $maxDivisor est supérieur à 55 : cela signifie qu'il y a 660 serveurs ou plus dans la liste
if ($averageNumberOfServersPerUpdate -ge 55){
    Write-Output "Attention, il y aura en moyenne plus de 55 serveurs à mettre à jour chaque semaine !"
}

# diviser le nombre de serveurs par le diviseur maximum pour savoir combien de serveurs seront mis à jours par semaine
$resultOfDivision = [math]::Ceiling($averageNumberOfServersPerUpdate)

# définir le nombre minimum de serveurs souhaité à MAJ chaque semaine
$minimumNumberOfServersPerUpdate = 47

# définir le nombre maximum de serveurs souhaité à MAJ chaque semaine
$maximumNumberOfServersPerUpdate = 52

# si $numberOfServers divisé par $maxDivisor (arrondi au supérieur) est inférieur au nombre minimum de serveurs souhaité
if([math]::Round($resultOfDivision) -lt $minimumNumberOfServersPerUpdate){
    <# alors on rentre dans la boucle : tant que le résultat de la division est inférieur à 47, retirer 1 à $maxDivisor
    et continuer à réessayer de diviser $numberOfServers par $maxDivisor-1#>
    Do{
        $maxDivisor --
        $resultOfDivision = [math]::Ceiling($numberOfServers / $maxDivisor)
    }While($resultOfDivision -lt $minimumNumberOfServersPerUpdate)
}


# définir $numberOfWeeks qui est le nombre de vagues de MAJ, qui est le $maxDivisor actualisé
$numberOfWeeks = $maxDivisor


# Créer une variable vide (tableau) pour stocker les tableaux "$week0", "$week1", ... jusqu'à $week$numberOfWeeks
$weeks = @()

# Créer les tableaux (variables) et les ajouter à la varialbe $weeks
for ($i = 0; $i -lt $numberOfWeeks ; $i++){
    # Créer le tableau avec les colonnes Client et Count vides
    $week = @(
        [PSCustomObject]@{
            Client = $null
            Count = $null
        }
    )
    
    # Ajouter le tableau créé au tableau $weeks
    $weeks += $week

    # créer une variable $week$i, où $i est l'indice de la boucle, de façon à ce qu'à la prochaine itération, la variable qui vient d'être créée ne soit pas effacée
    Set-Variable -Name "week$i" -Value $week
}
$weeks


<#tentative 1 pour chaque ligne de $tabClientsRanked
foreach ($item in $tabClientsRanked){
    # si la case Week est vide
    if($item.Week -like $null){
        # alors pour chaque week vide du tableau $weeks
        foreach($itemWeeks in $weeks){
            # alimenter le premier tableau vide
            Do{
                += 
            # tant que le count est inférieur à $minimumServersPerUpdate et inférieur à $maximumNumberOfServersPerUpdate
            }While($week.Count-lt $minimumNumberOfServersPerUpdate -and $week.Count -lt $maximumNumberOfServersPerUpdate)
        } 
    }
}#>

<#tentative 2
while ($tabClientsRanked | Where-Object { $_.Week -eq "" }) {
    foreach ($week in $weeks) {
        $currentWeek = $week.Count | Measure-Object -Sum
        if ($currentWeek.Sum -ge 47 -and $currentWeek.Sum -le 52) {
            $lineToAdd = $tabClientsRanked | Where-Object { $_.Week -eq "" } | Select-Object -First 1
            if ($lineToAdd) {
                $week += $lineToAdd
                $lineToAdd.Week = [array]::IndexOf($weeks, $week)
            }
        }
    }
}#>


#afficher les résultats (rien ne s'affiche comme je le souhaite dans un cas comme dans l'autre)
$week0
$week1
$week2
$week3
$week4
$week5
$week6
Dernière édition: il y a 1 mois 1 jour par gerome.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 1 mois 1 jour - il y a 1 mois 1 jour #33296 par Laurent Dardenne
QQ remarques,

pour
# connaître le nombre d'occurrences uniques de la colonne Client : on crée une variable $occurrences qui est une collection
$occurrences = $datas | Group-Object -Property Client
Attention $occurrences est une collection DE GROUPES.

Pour
# compter le nombre de serveurs
$numberOfServers = $datas.Length

Utiliser de préférence la propriété Count :
# compter le nombre de serveurs
$numberOfServers = $datas.Count

En passant cette ligne est dupliquée dans le code présenté.

Ici :
# définir une alerte si le nombre de serveurs divisé par $maxDivisor est supérieur à 55 : cela signifie qu'il y a 660 serveurs ou plus dans la liste
if ($averageNumberOfServersPerUpdate -ge 55) {
Write-Output "Attention, il y aura en moyenne plus de 55 serveurs à mettre à jour chaque semaine !"
}

Utilise Write-host, Write-Output émet des données dans le pipeline ce qui peut créer des bugs difficile à détecter surtout lorsqu'on débute sous Powershell.

Ici :
# si la case Week est vide
if($item.Week -like $null)

Avec un tableau ([Array]) utilise l'opérateur -EQ et inverse l'opérande $null (c'est préférable sous Powershell ) :
if($Null -eq $item.Week )


Ici
# Créer les tableaux (variables) ET les ajouter à la variable $weeks

c'est pour moi redondant, car on accède aux mêmes données mais pas de la même manière.
Le tableau $weeks contient toutes les données des variables week1, week2 etc.

$Indice=0
$Weeks[Indice] -EQ $week$Indice , c'est dire $week0

Et si $Weeks[0] -EQ $week0 on peut écrire $week0 = $Weeks[0]


Pour
>>#afficher les résultats (rien ne s'affiche comme je le souhaite dans un cas comme dans l'autre)
>>comme je le souhaite
C'est la question à laquelle tu n'as pas répondu ( cf. mon dernier post).
Qu'est que tu veux avoir comme résultat ? Pour le moment on peut sauter le "comment le faire".

Je pense que ce que tu comptes coder est très simple, mais là sans données (avant,après) je suis un peu court en proposition :-)

>>je me rends compte que je ne sais pas manipuler les données d'un tableau, ce qui est problématique car $tabClientsRanked et $weeks en sont !
Manipuler un tableau est très simple, j'ai l'impression que ton problème est plus dans l'association des clients et des semaine de planification.

En fait laisse tomber provisoirement l'intégralité de ce code et ne reprend que ce que tu veux comme résultat (il faut isoler la difficulté) quitte à utiliser des données de test préparées. Les clients Riri, Fifi et Loulou feront l'affaire ;-)[/code][/code]

Tutoriels PowerShell
Dernière édition: il y a 1 mois 1 jour par Laurent Dardenne.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 1 mois 20 heures #33297 par gerome
Réponse de gerome sur le sujet créer un tableau de tableaux
$occurrences est une collection DE GROUPES
Qu'est-ce qu'un groupe ? Je comprends que cela a un rapport avec la cmdlet Group-Object qui affiche des objets dans des groupes
Mais en fait, qu'est-ce qu'une collection ?
Est-ce qu'en lisant le tuto "La notion d'objet sous PowerShell" cela pourra répondre à mes questions ?

Je vais supprimer la ligne $numberOfServers = $datas.Length en trop et remplacer .length par .count (pourquoi remplacer .length par .count ?)

Il m'est contre intuitif d'inverser l'opérande $null, mais je vais tâcher d'y penser à l'avenir.

Quel est le résultat que je veux obtenir ?

D'abord, la variable $tabClientsRanked se présente ainsi :

Client                Count   Week
                  
        ----
RIRI                     50    
FIFI                      50    
LOULOU              50    

La variable $weeks se présente ainsi
Client                Count
                  
Et les variables $week0, $week1, etc. se présentent aussi ainsi :

Client                Count
                  

Revenons à la variable $tabClientsRanked : la colonne Week est vide. Pour chaque ligne ligne dont la colonne est vide, je vais affecter le client au premier $weekN disponible. Dans notre cas, il s'agit de $week0, car nous commençons tout juste le remplissage. Donc on met RIRI dans $week0, et on écrit 0 sur la ligne de RIRI dans $tabClientsRanked :

Client                Count   Week
                  
        ----
RIRI                     50         0
FIFI                      50    
LOULOU              50    

Voici ce que donne $week0 :
Client                Count
                  
RIRI                      50

Maintenant que la propriété Count de $week0 vaut 50, on va remplir $week1 qui est encore vide : on parcours $tabClientsRanked, et on affecte FIFI car RIRI n'est plus dispo : sa propriété Week est 0.

Et ainsi de suite jusqu'à ce que toutes les variables $weekN soient remplies et que toutes les propriétés Week de $tabClientsRanked portent des numéros.
Naturellement, j'ai pris des cas simples parce que dans ce cas tous les clients valent 50, mais s'ils avaient valu 25, j'en aurai mis 2 par $week. Dans le cas réel, on a des clients dont le Count se situe entre 1 et 50.

Est-ce plus clair ainsi ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 1 mois 10 heures #33298 par Laurent Dardenne
>>cela a un rapport avec la cmdlet Group-Object qui affiche des objets dans des groupes
Oui c'est cela.Tu as le résultat du regroupement et une propriété Group qui contient tous les éléments répondant aux critères de regroupement.

>>Mais en fait, qu'est-ce qu'une collection ?
Le mieux est de reprendre l'explication de Wikipedia :

En programmation informatique, une collection est un regroupement d'un nombre variable d'éléments de données (éventuellement zéro) ...
Une collection est un concept ... et ne prescrit pas une implémentation spécifique en tant que structure de données concrète...

Il aussi ceci en plus technique. On y trouve quel choix faire selon ses besoins et les performances.

>>Est-ce qu'en lisant le tuto "La notion d'objet sous PowerShell" cela pourra répondre à mes questions ?
Non pas sur ce point.

>>pourquoi remplacer .length par .count ?
C'est plus une convention, et facilite la relecture. Et powershell en interne ajouter une propriété 'count' à la plupart des objets qui n'en possèdent pas :
(2).Count
#1
$service=get-service|select-object -first 1
$service
$service.count
1

>>Il m'est contre intuitif d'inverser l'opérande $null
Oui ce n'est pas courant, l'opérande -EQ sur un tableau recherche tous les éléments qui seraient à $null, on ne teste pas le contenant (le tableau) mais le contenu (les objets du tableau).
Cela peut créer des bugs, par méconnaissance de ce comportement. La difficulté avec PS est connaitre le plus tôt possible ces types de comportement 'bizarre'.


>>Est-ce plus clair ainsi ?
Oui.

Un dernier point :
>>mais s'ils avaient valu 25, j'en aurai mis 2 par $week.
2 clients ?
2 clients dans le tableau d'une semaine numéroté ( 0..6) ?

Client Count Week ----
RIRI 25 0
FIFI 25 0
LOULOU 50 1
etc


$Week0
Client Count
RIRI 25
FIFI 25

C'est cela ?

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 1 mois 8 heures #33299 par Laurent Dardenne
Une visualisation de ce j'ai compris comme résultat attendu :
#crée des constantes, la semaine une a pour valeur l'indice zéro d'un tableau
New-Variable -Name SemaineUne -Option ReadOnly -Scope Script -Value 0
New-Variable -Name SemaineDeux -Option ReadOnly -Scope Script -Value 1

#Sinon utiliser deux notions, un numéro de semaine et un indice de tableau correspond
New-Variable -Name SemaineUne -Option ReadOnly -Scope Script -Value 1 -Force
New-Variable -Name SemaineDeux -Option ReadOnly -Scope Script -Value 2 -Force

New-Variable -Name IndiceSemaineUne -Option ReadOnly -Scope Script -Value ($SemaineUne - 1)
New-Variable -Name IndiceSemaineDeux -Option ReadOnly -Scope Script -Value ($SemaineDeux - 1)

Function New-Week {
    param(
        [Parameter( position = 0)]
        $Client,
        [Parameter(, position = 1)]
        $Count
    )

    [pscustomobject]@{
        PSTypeName = 'Week'; # nom du type 'personnalisé' Powershell sinon le type sera tjr PSCustomObject
        Client     = $Client;
        Count      = $Count;
    }
}

Function New-Client {
    param(
        [Parameter(Mandatory = $True, position = 0)]
        $Name,
        [Parameter(Mandatory = $True, position = 1)]
        $Count,
        [Parameter(position = 2)]
        $WeekNumber
    )

    [pscustomobject]@{
        PSTypeName = 'Client';
        Name       = $Name;
        Count      = $Count;
        WeekNumber = $WeekNumber;
    }
}


function Get-NextWeek {
    param([int]$WeekNumber, $Count)

    Write-Warning "Add week '$WeekNumber' : '$count'"
    $Week = $script:AllWeeks[$WeekNumber]
    if ($Week.Count -eq 0) {
        Write-Warning "`t semaine '$WeekNumber' vide "
        return $weekNumber
    } else {
        #la somme de tous les serveurs à traiter pour une semaine
        $Max = 0
        foreach ($Current in $Week)
        { $Max += $Current.Count }
        Write-Warning "`t max=$max"

        If ( $Max -ge 50 )
        { Write-Warning "`t renvoi le numéro de la prochaine semaine"; return ($weekNumber + 1) }
        else {
            Write-Warning "`t renvoi le même numéro de semaine"; return $weekNumber
        }
    }
}

$Clients = @(
    New-Client Riri 50 $null
    New-Client Fifi 50 $null
    New-Client Loulou 50 $null
    New-Client ABC 10 $null
    New-Client RAS 30 $null
    New-Client TEST 10 $null
    New-Client Dernier 10 $null
)

#Limite du nb de semaine à créer
$NbWeek = 7

#Tableau d'objet d'une taille fixe
$script:AllWeeks = New-Object Object[] $NbWeek

#Affecte une collection, de taille inconnue, dans chaque semaine à créer
#On crée un tableau de tableau
0..($NbWeek - 1) | ForEach-Object { $Indice = $_ ; $script:AllWeeks[$indice] = [System.Collections.ArrayList]::New() }

$CurrentWeek = 0 #Indice de zéro à six

foreach ($Client in $Clients) {
    If ($null -eq $Client.WeekNumber) {
        # calcule si l'affectation d'un nouveau client est possible pour la semaine en cours de traitement
        Write-Warning "Before current $CurrentWeek"
        $CurrentWeek = Get-NextWeek $CurrentWeek $Client.Count
        Write-Warning "After current $CurrentWeek"

        if ($CurrentWeek -ge ($nbWeek - 1) )
        { return } # toutes les semaines sont remplies, fin de la boucle
        #ajoute un client à la semaine en cours
        $liste = $script:AllWeeks[$CurrentWeek]
        $Liste.Add( (New-Week $Client.Name $Client.Count)) > $null

        Write-Warning "list count $($Liste.Count)"
        $Client.WeekNumber = $CurrentWeek
    }
    #else CLient suivant
}
#les clients sont à jour

#résultat à utiliser ligne par ligne dans une console
#sinon l'affichage est 'bizarre'
$AllWeeks[0]
$AllWeeks[1]
$AllWeeks[2]
$AllWeeks[3]
$AllWeeks[4]
$AllWeeks[5]

$lients


#nom des types des variable utilisées
$clients.pstypenames
$clients[0].pstypenames

#tableau
$AllWeeks.pstypenames
#tableau de tableau
$AllWeeks[0].pstypenames
#Premier élement du premier tableau
$AllWeeks[0][0].pstypenames


$AllWeeks[$IndiceSemaineUne].pstypenames
$AllWeeks[$IndiceSemaineUne][0].pstypenames

Write-host "`$AllWeeks[$IndiceSemaineUne][0].pstypenames contient un objet personnalisé de type '$($AllWeeks[$IndiceSemaineUne][0].pstypenames[0])'"

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 4 semaines 1 jour #33300 par Laurent Dardenne
Pour la fonction Get-NextWeek le paramètre $Count n'est pas utilisé.
Il faut peut être ajouter un contrôle afin que dans la semaine sélectionné le nb de serveurs ne dépasse 50 : ($max=40 + $Count=40) -> $Max=80 ?
A toi de voir...

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.073 secondes
Propulsé par Kunena