Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Evan Miller Ranking Items with Star Ratings, in JavaScript
"use strict";
// based on unutbu's stackoverflow answer
// https://stackoverflow.com/a/40958702/54829
// which is based on Evan Miller's blog post
// http://www.evanmiller.org/ranking-items-with-star-ratings.html
function sum(array) {
return array.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
}
function reverseRange(K) {
var result = Array(K);
for (var i = 0; i < K; i++) result[i] = K - i;
return result;
}
function f(s, ns) {
var N = sum(ns);
var K = ns.length;
var total = 0;
for (var i = 0; i < K; i++) {
total += s[i]*(ns[i]+1);
}
return total / (N + K);
}
function starsort(ns) {
var N = sum(ns);
var K = ns.length;
var s = reverseRange(K);
var s2 = s.map(x => x*x);
var z = 1.65;
var fsns = f(s, ns);
var fs2ns = f(s2,ns);
return fsns - z*Math.sqrt(
(f(s2,ns) - fsns*fsns)/(N+K+1)
);
}
console.log(starsort([60, 80, 75, 20, 25]));
@dfabulich

This comment has been minimized.

Copy link
Owner Author

dfabulich commented Oct 22, 2018

I also needed this in SQL.

SELECT (
  (5*(rated5+1)+4*(rated4+1)+3*(rated3+1)+2*(rated2+1)+1*(rated1+1))
  /(5+rated5+rated4+rated3+rated2+rated1)
)-1.65*SQRT(
  (
    (
      (25*(rated5+1)+16*(rated4+1)+9*(rated3+1)+4*(rated2+1)+1*(rated1+1))
      /(5+rated5+rated4+rated3+rated2+rated1)
    )
    - POWER(
      (
        (5*(rated5+1)+4*(rated4+1)+3*(rated3+1)+2*(rated2+1)+1*(rated1+1))
        /(5+rated5+rated4+rated3+rated2+rated1)
      ), 2
    )
  )
  /(6+rated5+rated4+rated3+rated2+rated1)
) as x FROM (select 60 as rated5, 80 as rated4, 75 as rated3, 20 as rated2, 25 as rated1) as mytable;

Writing the SQL by hand is a hassle, so I wrote this ES2015 JS to generate SQL for any K.

const K = 5;
const z = 1.65;

const prefix = 'rated';

const range = [...Array(K).keys()];

const N = range.map(x => prefix+(K-x)).join('+');

const s = range.map(x => K-x);
const s2 = s.map(x => x*x);

const fsnsSum = [];
for (let i = 0; i < K; i++) {;
	fsnsSum.push(`${s[i]}*(${prefix}${K-i}+1)`);
}
const fsns = `((${fsnsSum.join('+')})/(${K}+${N}))`;
const fs2nsSum = [];
for (let i = 0; i < K; i++) {;
	fs2nsSum.push(`${s2[i]}*(${prefix}${K-i}+1)`);
}
const fs2ns = `((${fs2nsSum.join('+')})/(${K}+${N}))`;

console.log(`${fsns}-${z}*SQRT((${fs2ns} - POWER(${fsns}, 2))/(${K+1}+${N}))`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.