Find first available serial based on list of strings?

后端 未结 4 1114
挽巷
挽巷 2021-01-26 02:34

Given a list of strings such as: apple01, apple02, and apple04, banana02, cherry01, how would you come up with t

4条回答
  •  终归单人心
    2021-01-26 02:44

    This could be the start of what you are looking for. I took a very similar approach as PetSerAl has done in his comment. I have made mine more verbose as it helps to take in what is happening here. Most of the explanation comes from comments in the code.

    # 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
    }
    

    We take the array of fruits and create an object array of fruit and indexes. Group those together by fruit and then determine the next available index based on all available indexes for that fruit. We add one to the highest possible index on the chance that they are all in use (no gaps). This is the case for cherry.

    apple03
    banana01
    cherry02
    

    Alternatively you could output the results to a variable and call the fruit you need from there if you don't need the whole list as output.

    # 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
    

    Which would net the output of:

    apple03
    

提交回复
热议问题