Specification: Return index of the first element you can remove that does not change the mean of the list by more than 0.1
Example input/output:
Input:
vals
id | value |
---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 1 |
Output:
1
Python - Imperative
def get_mean(ls): sum = 0 for e in ls: sum += e['value'] return sum/len(ls) def changing_mean(vals): start_mean = get_mean(vals) for i,elem in enumerate(vals): new_ls = vals[:i] + vals[i+1:] mean = get_mean(new_ls) if abs(mean - start_mean) < 0.1: return i return None
Python - Functional
def changing_mean(vals): start_mean = sum([l['value'] for l in vals])/len(vals) diff = lambda m, sm: abs(m - sm) for i,elem in enumerate(vals): new_ls = [x['value'] for x in vals if x != elem] mean = sum(new_ls)/len(new_ls) if diff(mean,start_mean) < 0.1: return i return None
Python - Pandas
def changing_mean(vals): mean = vals.value.mean() mean_without = vals.apply(lambda row: vals[vals.id != row.id].value.mean(), axis=1) return vals[(mean_without - mean).abs() < 0.1].id.tolist()
R - Tidyverse
library(data.table) changing_mean <- function(vals) { global_mean <- mean(vals$value) setDT(vals)[, mean_change := abs(global_mean - mean(vals[id != .BY, value])), by = id] %>% filter(mean_change < 0.1) %>% slice(which.min(id)) %>% pull(id) }
SQL - SQLite
SELECT id FROM vals v1 WHERE ABS(( SELECT AVG(value) FROM vals v2 WHERE v1.id != v2.id ) - (SELECT AVG(value) FROM vals)) < 0.1
Datalog - Souffle
.decl avg_except(I:number, Avg:float) avg_except(I, Avg) :- vals(I, _), N = sum 1.0 : { vals(J, _), I != J }, Total = sum V : { vals(J, V), I != J }, Avg = Total / N. changing_mean(I) :- vals(I, _), N = sum 1.0 : vals(_, _), Total = sum V : vals(_, V), Avg = Total / N, avg_except(I, AvgExcept), ((Avg > AvgExcept, Avg - AvgExcept < 0.1); (Avg < AvgExcept, AvgExcept - Avg < 0.1)).
Q - kdb+
diffs: {abs avg vals[`value] - avg (vals[`value] where vals[`id] <> x)} each vals[`id]; changing_mean: first vals[`id] where diffs < 0.1