Group a List by Frequency

Mathematica, 43 bytes

Union/@SortBy[l=#,f=-l~Count~#&]~SplitBy~f&

Try it online! (Using Mathics.)

Alternatively:

SortBy[Union[l=#],f=-l~Count~#&]~SplitBy~f&

Pyth, 8 7 bytes

_{M.g/Q

Try it online!

1 byte thanks to FryAmTheEggman.


JavaScript (ES6), 95 101 bytes

a=>a.map(x=>(o[a.map(y=>n+=x!=y,n=0)|n]=o[n]||[])[x*x+(x>0)]=x,o=[])&&(F=o=>o.filter(a=>a))(o).map(F)

How?

For each element x of the input array a, we compute the number n of elements of a that are different from x:

a.map(y => n += x != y, n = 0) | n

We use the indices n and x to fill the array o:

(o[n] = o[n] || [])[x * x + (x > 0)] = x

Edit: Because JS doesn't support negative array indices, we need the formula x * x + (x > 0) to force positive indices.

This gives us an array of arrays containing the unique elements of the original list, grouped by frequency and ordered from most frequent to least frequent.

However, both the outer array and the inner arrays potentially have many empty slots that we want to filter out. We do this with the function F, applied to o and each of its elements:

F = o => o.filter(a => a)

Test cases

let f =

a=>a.map(x=>(o[a.map(y=>n+=x!=y,n=0)|n]=o[n]||[])[x*x+(x>0)]=x,o=[])&&(F=o=>o.filter(a=>a))(o).map(F)

console.log(JSON.stringify(f([1,2,3]))) // [[1,2,3]]
console.log(JSON.stringify(f([1,1,1,2,2,3,3,4,5,6]))) // [[1],[2,3],[4,5,6]]
console.log(JSON.stringify(f([1,1,1,4,5,6,6,6,7,7,8,8,8,8,8,8,8,9,5,6,5,6,5,6,5,6,-56]))) // [[6, 8],[5],[1],[7],[9,4,-56]]
console.log(JSON.stringify(f([]))) // []