Skip to content

Instantly share code, notes, and snippets.

@wdiasvargas
Created August 9, 2016 00:46
Show Gist options
  • Save wdiasvargas/10282eee7f93d65ed5a58f365b321809 to your computer and use it in GitHub Desktop.
Save wdiasvargas/10282eee7f93d65ed5a58f365b321809 to your computer and use it in GitHub Desktop.
'use strict'
/**/
function moda (arr) {
return ((arr.sort((a, b) =>
(arr.filter(v => v === a).length) - (arr.filter(v => v === b).length))
).pop())
}
module.exports = moda
console.log(moda([1,2,3,4,5])) //amodal nao tem moda(nao deveria aparecer nada)
console.log(moda([1,2,3,4,5,5])) //modal tem moda(5) pois aparece mais vezes
console.log(moda([1,2,3,3,4,4,5,5])) //plurimodal tem mais de 1 moda(3,4,5)pois aparecem mais vezes
@suissa
Copy link

suissa commented Aug 9, 2016

@cyberglot
Copy link

cyberglot commented Aug 9, 2016

const count = (arr) => (arr.reduce(reducer, {}));

const reducer = (obj, value) => {
  obj[value] = obj[value] ? obj[value] + 1 : 1;
  return obj;
};

const findMaxes = (counting) =>
        (Object.keys(counting)
         .reduce((maxes, key) => {
                   if (maxes.max == counting[key]) return {max: maxes.max, values: maxes.values.concat(Number(key))};
                   if (maxes.max >  counting[key]) return maxes;
                   if (maxes.max <  counting[key]) return {max: counting[key], values: [key]};
                   return maxes; // just in case
                 },
                 {max: -1, values: []}));

const getValues = (length, maxes) => (maxes.values.length == length ? [] : maxes.values);

const mode = (arr) => getValues(arr.length, findMaxes(count(arr)));

console.log(mode([1,2,3,4,5])); // []
console.log(mode([1,2,3,4,5,5])); // [5]
console.log(mode([1,2,3,3,4,4,5,5])); // [3, 4, 5]

Eu achei melhor dar uma enxugada e diminuir o número de computações, por ex, eu não achava que era necessário sortear e mapear várias vezes os dados. Eu fiz usando js puro, talvez desse para condensar mais usando algumas libs.

@lukaswilkeer
Copy link

@cyberglot não creio que há necessidade de usar uma lib. Iria ficar mais condensado essa função em si, porem o "projeto" ficaria mais inchado.

@suissa
Copy link

suissa commented Aug 10, 2016

Nesse caso aqui tem alguma forma de continuar na sequencia do reduce? @haskellcamargo

  const filtrada = filtrarModa(contagem, acharMaior(mapearParaArray(contagem)))

@cyberglot
Copy link

@lukaswilkeer mas ramda é uma boa opção para projetos, e vc pode carregar só o que precisa.

@suissa 😉

@suissa
Copy link

suissa commented Aug 10, 2016

@suissa
Copy link

suissa commented Aug 10, 2016

Esse reduce da @cyberglot humilhou hein! Eu não tenho nem a lógica de pensar dessa forma AINDA.

@ribaptista
Copy link

ribaptista commented Aug 11, 2016

Apenas uma sugestão:

const toArray = obj => Object.keys(obj).map(key => obj[key]);

const summarize = numbers => toArray(numbers.reduce(summarizeFn, {}));

const summarizeFn = function(summary, num) {
  summary[num] = summary[num]
      ? { num, count: summary[num].count + 1 }
      : { num, count: 1 }
  return summary;
};

const findMode = summary => summary.reduce(findModeFn, 0);

const findModeFn = (max, { count }) => count > max ? count : max;

const filterMode = (summary, mode) => summary.filter(({ count }) => count == mode);

const getValues = items => items.map(({ num }) => num);

const mode = function(numbers) {
  const summary = summarize(numbers);
  const mode = findMode(summary);
  const modeItems = filterMode(summary, mode);
  return modeItems.length == summary.length ? [] : getValues(modeItems);
}

console.log(mode([]));  // []
console.log(mode([1, 2, 3, 4, 5]));   // []
console.log(mode([1, 1, 3, 3, 4, 4, 5, 5]));  // []
console.log(mode([1, 1, 3, 4, 5]));   // [1]
console.log(mode([1, 3, 3, 3, 5]));   // [3]
console.log(mode([1, 1, 3, 3, 4, 5]));  // [1, 3]

@suissa
Copy link

suissa commented Aug 16, 2016

MUITO BOM @ribaptista

Só no final o [] tem q retornar 0 por ser amodal, mas ficou MUITO SIMPLES e legível!

@ribaptista
Copy link

ribaptista commented Aug 24, 2016

Muito obrigado, @suissa!

Mas eu acredito que num cenário real seja desejável a função retornar [] ao invés de zero quando o input é amodal. Assim a função é consistente quanto ao tipo de dado do retorno (sempre um array). Facilita para o código que chamar essa função lidar sempre com o mesmo tipo de retorno.

@wkrueger
Copy link

wkrueger commented Feb 3, 2017

Escrevi um e ficou uma merda rs

const histogram = arr => arr.reduce( (result, item) => {
    result[item] = (result[item] || 0) + 1
    return result
}, {}) 

const pairs = obj => Object.keys(obj).map( key => [key, obj[key]] )

function mode(arr) {
    let result = pairs(histogram(arr))
        .sort( (a,b) => b[1] - a[1] )
        .filter( (item, index, source) => item[1] === source[0][1] )
        .map( item => item[0] ) 
    return result.length === arr.length ? [] : result
}

console.log( mode([1,2,3,4,5]) )
console.log( mode([1,2,3,4,5,5]) )
console.log( mode([1,2,3,4,4,5,5]) )

Sobre "código puramente funcional", é só extrair os constructos imperativos em funções? Pois em baixo nível sempre será imperativo... Dá na mesma...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment