Find the frequency of triplets in a phrase

Perl 6,  67  57 bytes

*.words.map({[~] .lc.comb(/\w/)}).rotor(3=>-2)».join(' ').Bag.perl

Try it

*.words.rotor(3=>-2).map({lc S:g/<-:L-:N-:Z>//}).Bag.perl

Try it

Expanded:

*\                # WhateverCode lambda (this is the parameter)
.words            # get a list of words
.rotor( 3 => -2 ) # grab 3, back up 2, repeat

.map({            # take those list of 3 elements

  lc              # lower case the following

  S               # remove
  :global         # globally
  /
    <- :L         # not a letter
     - :N         # not a number
     - :Z         # not a space  (inserted when the current list is stringified)
    >
  //

})
.Bag              # turn it into a Bag
.perl             # return the structure as an `EVAL`able Str

returns something like

("bb a cc"=>1,"aa bb a"=>1,"a cc a"=>1,"a bb a"=>3,"bb a bb"=>2,"cc a bb"=>1).Bag

Retina, 50 bytes

T`lLd p`lld _
M!&`(\b\w+ ??){3}
O`
$
¶
D`
¶+
:$.&¶

Try it online!

Explanation

T`lLd p`lld _

Replace all uppercase letters with lowercase ones, keep other letters, digits and spaces unchanged and delete other characters.

M!&`(\b\w+ ??){3}

Find all possible matches of three words in a row.

O`

Sort the matches, so equal triplets end next to each other.

$
¶

Add a newline at the end.

D`

Remove duplicate lines (this will keep the newlines at the end of them).

¶+
:$.&¶

Sequences of newlines are now the counts we need, replace them with a delimiter (:) followed by the count and a newline.


Jelly, 18 13 bytes

ŒlḲf€ØBṡ3ṢŒr'

A monadic link (function) that returns a list, each entry contains a list of 3 lists of characters (the words) and a count.

Try it online! - the footer formats the results (as a full program everything just gets smushed together by the implicit print).

How?

ŒlḲf€ØBṡ3ṢŒr' - Main link: s
Œl            - convert s to lowercase
  Ḳ           - split on spaces
     ØB       - base digit yield "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
   f€         - filter keep for €ach
       ṡ3     - all overlapping slices of length 3
         Ṣ    - sort
            ' - call the previous monadic link without vectorising
          Œr  -     run length encode