derhoeppi
Goto Top

PowerShell nächste freie Nummer finden

Hallo,

vor einem knappen Jahr hat mich Uwe bereits einmal zu dem Thema unterstützt. Ich möchte die damalige Anforderung noch einmal erweitern.

Anforderung konnte damals so umgesetzt werden:
$arr = @(1,5,3,4,6)
$ids = $arr | sort
for($i=0;$i -lt $ids.count;$i++){
    if ([int]$ids[$i] -ne [int]($ids[$i+1]-1)){
        $nextID = [int]$ids[$i] + 1
        break
    }
}
$nextID

Nun habe ich eine Array dessen Count in einer Variable steht. Anhand dieser Variable möchte ich nun die nächsten x (Count-Wert) freien Nummern erhalten. In dem Array von oben sollten z.B. die Nummern 2,7,8,9 bei einem Count Wert von 4 zurückgegeben werden.

Gruß
derhoeppi

Content-ID: 285331

Url: https://administrator.de/contentid/285331

Ausgedruckt am: 24.11.2024 um 05:11 Uhr

colinardo
Lösung colinardo 12.10.2015, aktualisiert am 09.05.2018 um 10:03:43 Uhr
Goto Top
Moin,
mal ein etwas anderer Ansatz ... wird ja sonst langweilig face-big-smile
$arr = @(1,5,3,4,6) | sort
$free = @()
$count = 4
# ----
[array]$free = @(compare (1..$arr[-1]) $arr -PassThru)
$next = $arr[-1]+1
if(($count-$free.length) -gt 0){
    1..($count - $free.Length) | %{$free += $next;$next++}
}
$free
Grüße Uwe

-edit- Fehler korrigiert (09.05.2018)
derhoeppi
derhoeppi 12.10.2015 um 13:31:41 Uhr
Goto Top
Hallo Uwe,
ich habe in der Zwischenzeit an der alten Schleife weitergearbeitet.

$b = @(a,b,c,d)
$arr = @(1,3,4,5)
$ids = $arr | Sort
Foreach ($c in $b){
$ids = $ids | Sort
for($i=0;$i -lt $ids.count;$i++){
    if ([int]$ids[$i] -ne [int]($ids[$i+1]-1)){
        $nextID = [int]$ids[$i] + 1
        $ids += $nextID
        break;
    }	
}
$nextID
}
Nun habe ich folgendes Problem. Im $arr befinden sich leider nicht nur „saubere“ Zahlen, sondern auch Zahlen mit einer oder zwei führenden Nullen. Aus diesem Grund erhalte ich bei bestimmten Zahlen Probleme. Im konkreten ist das mein Array $arr=@(02,50,60,61) . In dem oben dargestellten Code erhalte ich als $nextID in der Reihenfolge die Zahlen 1, 3, 1, 2. Dies geschieht aus meiner Sicht durch die führende 0. Wie kann ich diese entfernen?
Gruß
derhoeppi
114757
114757 12.10.2015 aktualisiert um 13:52:22 Uhr
Goto Top
Moin derhoeppi
Dies geschieht aus meiner Sicht durch die führende 0. Wie kann ich diese entfernen?
nope, glaube ich nicht, denn die Zahlen werden ja mit [int] in Integer umgewandelt. Kannst du ja mal selber probieren
[int]02
Das geht so in der Art wie du das hier mit zwei Schleifen versuchst nicht.

@colinardo's Vorschlag geht hier im Test bei mir ...

Gruß jodel32
derhoeppi
derhoeppi 12.10.2015 um 15:22:33 Uhr
Goto Top
Hallo jodel,

ich habe nun Uwe sein Beispiel abgetippt und getestet. Als Ergebnis erhalte ich jedoch Zahlen zwischen 3 und 59. Derzeit durchlaufe ich eben die foreach Schleife. In jedem Durchlauf der foreach Schleife benötige ich eine freie Zahl, die nicht bereits in dem $arr vorhanden ist.

Gruß
derhoeppi
114757
114757 12.10.2015 aktualisiert um 15:35:03 Uhr
Goto Top
Hmm hier nicht , wahrscheinlich ein Fehler beim abtippen ...
Mein Array
3,5,6,7
Dann bei $count = 4 Ausgabe:
1,2,4,8
Du wollest doch wenn weniger als Count vorhanden sind mit dem höchsten Wert es Arrays weiter gemacht wird, hier ist also die 8 zusätzlich dazu gekommen da nicht mehr Lücken drin waren.
derhoeppi
derhoeppi 12.10.2015 um 16:22:39 Uhr
Goto Top
Hallo,
ich habe tatsächlich einen Fehler beim Abtippen gehabt. Ich habe nun den Teil in meinem Skript übernommen und an die foreach Schleife angepasst.

Danke

Gruß
derhoeppi
colinardo
colinardo 12.10.2015 um 18:19:22 Uhr
Goto Top
Wenns das dann war, den Beitrag bitte noch auf gelöst setzen. Merci.
derhoeppi
derhoeppi 09.05.2018 aktualisiert um 08:07:01 Uhr
Goto Top
Hallo Uwe,

für mein Skript habe ich mich damals für deinen Code entschieden und dieser funktionierte nun fast 2,5 Jahre fehlerfrei. Der Code
$arr = @(1,5,3,4,6) | sort
$free = @()
$count = 4
# ----
$free = [array](compare (1..$arr[-1]) $arr -PassThru)
$next = $arr[-1]+1
if(($count-$free.length) -gt 0){
    1..($count - $free.Length) | %{$free += $next;$next++}
}
$free

macht jetzt aber Probleme, weil das $arr keine freien Zahlen mehr hat. Das bedeutet im Beispiel des Codes das $arr = @(1,2,3,4,5,6) voll ist. Die Variable $next spuckt mir folgerichtig die 7 als nächste freie Zahl aus, aber $free wird mit der Zahl 24 zurückgegeben.
Wie kann ich mir nun die nächsten freien Zahlen anhand des $count ausgeben lassen bzw. diese in $free speichern? Am liebsten wäre es mir, wenn er mit die nächsten 4 Zahlen aus dem $free und $next generiert.
colinardo
Lösung colinardo 09.05.2018 aktualisiert um 10:04:06 Uhr
Goto Top
Hallo @derhoeppi .
Uups face-wink. Das kommt wegen dem Compare. Das liefert $null statt einem leeren Array zurück wenn das Array übereinstimmt und dann wird natürlich bei dem Operator += eine Addition von Zahlen angenommen statt dem Hinzufügen als Array Element.
Um dass zu fixen reicht es wenn man in Zeile die den Rückgabewert der Variablen zwingend als Array deklariert:
[array]$free = @(compare (1..$arr[-1]) $arr -PassThru)

Sorry.

Grüße Uwe

p.s. ich werden es oben im Ursprungsbeitrag noch korrigieren.
derhoeppi
derhoeppi 17.05.2018 um 07:42:11 Uhr
Goto Top
Hallo Uwe,

in dem obigen Beispiel funktioniert es und ich war damit in meinen Tests auch glücklich. Nun arbeite ich es wieder in meinen gesamtes Skript ein und es funktioniert nicht. Dafür habe ich folgendes Problem ausgemacht. Die Elemente vom $arr werden nicht vom Typ Integer ausgegeben, sondern als String. Das macht dahingehend Sinn, weil ich eine Liste von Systemnamen einlese, die eine fortlaufende Zahl besitzen. Über die Methode TrimStart entferne ich das Präfix, so dass nur noch die Zahlen übrig bleiben. Ich schreibe das Ergebnis von der TrimStart Methode in ein neues Array. Bisher hat es funktioniert.

Komisch ist, dass wenn das $arr aus den Zahlen 1 und 10 besteht, die Interpretation des Arrays auf Integer fällt. Habe ich keine Zahl mehr frei also 1 bis 10 dann interpretiert er es als String.
Hast du einen Tipp wie ich sicherstellen kann, dass die Zahlen, die ich mit der Methode TrimStart gewinne auf jeden Fall als Integer im Array landen?
colinardo
Lösung colinardo 17.05.2018 aktualisiert um 08:18:34 Uhr
Goto Top
TrimStart hat als Output den Typ String, ergo ist das Ergebnis davon ein String und kein Integer. Also musst du den String wieder in einen Integer wandeln indem du die String Variable entweder explizit mit [int] prefixt oder eben die Convert-Methoden dazu benutzt. Powershell macht zwar vieles implizit aber du musst darauf achten mit welchen Typen du hantierst face-wink.
derhoeppi
derhoeppi 17.05.2018 um 08:28:02 Uhr
Goto Top
Hallo Uwe,

ich habe gerade im Hintergrund daran gearbeitet und habe die Lösung ebenfalls gefunden. Das Array wird nun so deklariert [int[]]$arr . Und nun funktioniert es endlich wieder.

Vielen Dank für deine Unterstützung.