根据字符串列表查找第一个可用的序列?

时间:2016-01-29 13:33:47

标签: string powershell azure

给定一个字符串列表,例如:apple01apple02apple04banana02cherry01,你会如何提出< em>第一个 每个类型的可用序列号 - 如果我询问apple03,则为apple,如果我询问,则为banana01 bananacherry02,如果我问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
}

4 个答案:

答案 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))