l0c0b0x
l0c0b0x

Reputation: 187

Better way to randomize from text file in Powershell

I have a working Powershell function that uses the System.Speech to read-out a random line from a text file, using the Get-Random cmdlet.

Unfortunately, the randomizer cmdlet doesn't seem to be doing such a good job by itself, as it repeats the same lines way too many times.

My text file contains just sentences.

function suggestion{
    $suggestion=(Get-Random -InputObject (get-content C:\Tools\linesoftext.txt))
    Add-Type -AssemblyName System.Speech 
    $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
    $synth.Speak($suggestion)
    }

I'm not sure if I can modify what I have, or rethink the way I'm trying to randomize the output--maybe by keeping track of what has been already played and loop? (I'm a bit stumped).

Upvotes: 2

Views: 2525

Answers (2)

TheMadTechnician
TheMadTechnician

Reputation: 36297

I like Mathias's suggestion of shuffling the lines at launch, but if you want to keep in the motif of randomly selecting a line, but just don't want to hear the same lines over and over again set a threshold that it won't repeat at and store that many items in a global variable, and then add the last spoken line to it, and remove the first item whenever you have it speak a line. Something like:

function suggestion{
    $lines = get-content C:\Tools\linesoftext.txt
    $suggestion= Get-Random -InputObject ($lines | Where{$_ -notin $global:RecentSuggestions})
    [array]$global:RecentSuggestions += $suggestion
    If($global:RecentSuggestions.count -gt 20){$global:RecentSuggestions = $global:RecentSuggestions | Select -Skip 1}
    Add-Type -AssemblyName System.Speech 
    $synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
    $synth.Speak($suggestion)
    }

That'll keep track of up to 20 lines, and exclude those from the list of lines to randomly select from.

Upvotes: 2

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174515

I'm loading it to my $profile and calling it from a Powershell command prompt.

In this case you could use your profile to read the lines into memory and then randomly shuffle them, this way the same line won't repeat. To advance through the list, you could employ a ScriptProperty, like so:

Add-Type -AssemblyName System.Speech -ErrorAction SilentlyContinue

# One synthesizer on per shell should be enough 
$__synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer

# Read lines of text into memory, shuffle their order
$__lines = Get-Content C:\Tools\linesoftext.txt |Sort-Object {Get-Random}

# Add a script property to the $__lines variable that always returns the next sentence
$ScriptProperty = @{
  Name = 'NextSentence'
  MemberType = 'ScriptProperty' 
  Value = {
    return $this[++$global:__idx % @($this).Count]
  }
}
Add-Member @ScriptProperty -InputObject $__lines 

# Speak the next sentence
function Get-Suggestion {
  $global:__synth.Speak($global:__lines.NextSentence)
}

# Define alias `suggestion -> Get-Suggestion`
Set-Alias suggestion Get-Suggestion

Upvotes: 1

Related Questions