给定一个字符串列表,例如:apple01
,apple02
和apple04
,banana02
,cherry01
,你会如何提出< em>第一个 每个类型的可用序列号 - 如果我询问apple03
,则为apple
,如果我询问,则为banana01
banana
和cherry02
,如果我问cherry
?
我的任务是自动创建Azure VM,这些字符串实际上是现有VM的主机名,正如Azure Powershell命令(Get-AzureRmResourceGroupDeployment -ResourceGroupName "$azureResGrpName2").DeploymentName
所报告的那样(或者任何有效的相似的东西。)
更新:这是我的工作代码:
$rgdNames = (Get-AzureRmResourceGroupDeployment -ResourceGroupName "$azureResGrpName").DeploymentName
$siblings = $rgdNames | Where-Object{$_ -match "^($hostname)(\d+)$" }
if ($siblings) {
# Make a list of all numbers in the list of hostnames
$serials = @()
foreach ($sibling in $siblings) {
# $sibling -split ($sibling -split '\d+$') < split all digits from end, then strip off everything at the front
# Then convert it to a number and add that to $serials
$hostnumber = [convert]::ToInt32([string]$($sibling -split ($sibling -split '\d+$'))[1], 10)
$serials += $hostnumber
}
foreach ($i in 1..$siblingsMax){ # Iterate over all valid serial numbers
if (!$serials.Contains($i)) { # Stop when we find a serial number that isn't in the list of existing hosts
$serial = $i
break
}
}
} else {
$serial = 1
}
答案 0 :(得分:1)
天真直接的解决方案将基于预生成语法有效名称列表。
查询已在使用的名称并将结果存储到集合中。
迭代使用过的名称集合,并从预先生成的集合中删除它们。
对预先生成的集合进行排序。
现在你有一个包含排序顺序的未使用名称的集合。选择任意数量的所需名称以供进一步使用。
答案 1 :(得分:1)
这似乎可以解决问题!
## Create variable to store number in
$spareNumber = $null
## we are presuming that they have already been seperated into groups
$apples = @("apples01","apples002","apples3","apples15")
## create an empty array
$num = @()
## You know what a foreach is right? ;)
foreach ($apple in $apples)
{
## the hard working part
## [convert]:: toint32 converts to, you guessed it... (and adds it to $num)
## $apple -split ($apple -split '\d+$') < split all digits from end, then strip off everything at the front
$num += [convert]::ToInt32([string]$($apple -split ($apple -split '\d+$'))[1], 10)
}
## count from 1 to 10, and pass to foreach
(1..10) | foreach {
##'when we find one that isn't in $num, store it in sparenumber and break out of this joint.
if (!$num.Contains($_)) {
$spareNumber = $_
break
}
}
## and here is your number...
$spareNumber
答案 2 :(得分:1)
这可能是您正在寻找的开始。我采用了与PetSerAl has done in his comment非常相似的方法。我让我更加冗长,因为它有助于了解这里发生的事情。大多数解释来自代码中的注释。
# Array of fruits/index values. Using string array as proof on concept.
$fruits = "apple01","apple02","apple04","banana02","cherry01"
# Regex -match the fruit name and index number. This also filters out lines that do not match the standard.
$fruityArray = $fruits | Where-Object{$_ -match '^(.+?)(\d+)$' } | ForEach-Object{
# Create a simple object that splits up the matched info into a fruit index object
[pscustomobject][ordered]@{
Fruit = $matches[1]
Index = [int]$matches[2]
}
}
# Group by fruit and then we can find the next available index within the groups
$fruityArray | Group-Object Fruit | ForEach-Object{
# For this fruit determine the next available index
$thisFruitGroup = $_
# Determine the highest index value. We add one in case all indexes are present from 1 to highest
$highestPossibleIndex = ($thisFruitGroup.Group.Index | Measure-Object -Maximum).Maximum + 1
# Check all possible indexes. Locating all that are free but filter the first one out
$nextAvailableIndex = 1..$highestPossibleIndex | Where-Object{$_ -notin $thisFruitGroup.Group.Index} | Select -First 1
# Take the fruit and add a padded index then pass that value to the pipeline.
'{0}{1:00}'-f $thisFruitGroup.Name, $nextAvailableIndex
}
我们采用水果数组并创建一个水果和索引的对象数组。通过水果将它们组合在一起,然后根据该水果的所有可用指数确定下一个可用的指数。我们在最高可能指数上添加一个它们全部使用的可能性(无间隙)。这是樱桃的情况。
apple03
banana01
cherry02
或者,如果您不需要将整个列表作为输出,您可以将结果输出到变量并从那里调用所需的水果。
# Group by fruit and then we can find the next available index within the groups
$availableIndexes = $fruityArray | Group-Object Fruit | ForEach-Object{
# For this fruit determine the next available index
$thisFruitGroup = $_
# Determine the highest index value. We add one in case all indexes are present from 1 to highest
$highestPossibleIndex = ($thisFruitGroup.Group.Index | Measure-Object -Maximum).Maximum + 1
# Check all possible indexes. Locating all that are free but filter the first one out
$nextAvailableIndex = 1..$highestPossibleIndex | Where-Object{$_ -notin $thisFruitGroup.Group.Index} | Select -First 1
# Take the fruit and add a padded index then pass that value to the pipeline.
[pscustomobject][ordered]@{
Fruit = $thisFruitGroup.Name
Index = $nextAvailableIndex
String = '{0}{1:00}'-f $thisFruitGroup.Name, $nextAvailableIndex
}
}
$availableIndexes | Where-Object{$_.Fruit -eq "Apple"} | Select-Object -ExpandProperty String
这将净输出:
apple03
答案 3 :(得分:-2)
如果首先出现的名称是纯字母,不包括任何数字,而不是数字。这很简单,你可以获得该char列表中存在的第一个数字或char的索引{1,2,3,4,5,6,7,8,9} 而且你可以创建substring(0,indexof(firstnumber))