2012-11-13 11 views
5

Ho un array riempito con valori int positivi, come posso normalizzare questo elenco in modo che il valore massimo sia sempre 100? Grazie in anticipo!Come normalizzare un elenco di numeri positivi in ​​JavaScript?

+4

[Cosa hai provato?] (http://whathaveyoutried.com/) – ruakh

+0

Sii più specifico. Cosa fai con i valori? moltiplicare/sbarazzarsi di loro? Sei dopo una percentuale, un rapporto? –

+2

Dovrai essere un po 'più specifico, qui. Se stai *** normalizzando i valori di *** in modo che il valore massimo venga ridimensionato per uguagliare esattamente 100, allora applicare quella scala a tutti gli altri numeri è *** NON *** andando a lasciarli come numeri interi. Quindi stai cercando di fare la scala numero più alta a esattamente 100, anche se poi avrai i float, o stai cercando di scartare numeri superiori a 100 (filtro) o clampare tutti i numeri superiori a 100 a 100, e lasciare il riposare da solo (distorcendo la scala), o stai cercando di fare qualcos'altro? – Norguard

risposta

21

L'idea è di trovare prima il numero più alto nella vostra array (utilizzando apply su Math.max), quindi trovare il rapporto tra quel numero più alto e 100.

Dopo di che, è solo una questione di loop attraverso l'array e dividendo tutti i numeri per quel rapporto:

var numbers = [3, 8, 45, 74, 123], 
    ratio = Math.max.apply(Math, numbers)/100, 
    l = numbers.length, 
    i; 

for (i = 0; i < l; i++) { 
    numbers[i] = Math.round(numbers[i]/ratio); 
} 

Ecco il violino: http://jsfiddle.net/XpRR8/


Nota: Sto utilizzando Math.round per arrotondare i numeri all'intero più vicino. Se invece preferisce tenerli come galleggianti, è sufficiente rimuovere la funzione di chiamata:

for (i = 0; i < l; i++) { 
    numbers[i] /= ratio; 
} 

Ecco il violino: http://jsfiddle.net/XpRR8/1/


Se non c'è bisogno di sostenere IE8 e di seguito, è possibile utilizzare Array.prototype.map():

var numbers = [3, 8, 45, 74, 123], 
    ratio = Math.max.apply(Math, numbers)/100; 

numbers = numbers.map(function (v) { 
    return Math.round(v/ratio); 
}); 

Ecco il violino: http://jsfiddle.net/XpRR8/2/


Se fai supporto IE8, ma sono in ogni caso utilizzando jQuery, è possibile utilizzare $.map() invece:

numbers = $.map(numbers, function (v) { 
    return Math.round(v/ratio); 
}); 

Ecco il violino: http://jsfiddle.net/XpRR8/3/


Aggiornamento: Come sottolineato di @wvxvw nei commenti sotto, se sei preoccupato per le implementazioni marginali che impongono un limite artificiale alla quantità di argomenti apply gestirà, quindi utilizzerà un ciclo anziché Math.max.apply.Ecco un esempio (supponendo né Array.prototype.map$.map sono disponibili):

var numbers = [3, 8, 45, 74, 123], 
    ratio = 0, 
    i = numbers.length; 

while (i--) numbers[i] > ratio && (ratio = numbers[i]); 

ratio /= 100; 
i = numbers.length; 

while (i--) numbers[i] = Math.round(numbers[i]/ratio); 

Ecco il violino: http://jsfiddle.net/XpRR8/4/


Se stai usando ES6, questo diventa ridicolmente semplice:

var numbers = [3, 8, 45, 74, 123]; 
var ratio = Math.max(...numbers)/100; 

numbers = numbers.map(v => Math.round(v/ratio)); 
+0

+1 per la risposta dettagliata. – Shmiddty

+0

@wvxvw - Interessante. [Ecco un test che usa 'apply' con 10.000 elementi] (http://jsfiddle.net/9HXv4/), e funziona perfettamente in tutti i principali browser; L'ho persino testato nei 5 browser IE più recenti (6-10). Essendo quello [la differenza di prestazioni sembra orientarsi verso 'apply'] (http://jsperf.com/math-max-apply-vs-loop), (e in IE <9 la differenza è * scaglionante *), I suggerire di attenersi a 'apply'. (Nota a margine: Firefox sembra utilizzare un voodoo pazzo per ottenere prestazioni anormali dal metodo del ciclo. –

+0

@wvxvw - Sebbene tu abbia ragione sul fatto che la mia implementazione del ciclo non fosse la più efficiente, usare il tuo loop non cambia molto l'immagine: le versioni precedenti di IE (dove, discutibilmente, queste ottimizzazioni sono maggiormente necessarie) continuano a preferire l'applicazione 'con un margine * ampio *. –

0

Bene, è possibile ottenere il valore massimo con Math.max.apply(arr), quindi eseguire il ciclo o utilizzare arr.map per moltiplicare tutti i numeri per 100/max. Fatto.

4

Ti piace questa

function Normalize(array, value) 
{ 
for(var i = 0, len = array.length; i < len; i++) 
{ 
    if(parseInt(array[i]) > value) array[i] = value; 
} 
} 

e poi usarlo:

var arr = []; 
arr.push(101); 
arr.push(5); 
arr.push(6); 
Normalize(arr,100); 
+2

Rispetto che stai cercando di aiutare ma hai appena fatto lavorare qualcuno per loro. : [Per la cronaca non ero il -1. – Snuffleupagus

+0

@Snuffleupagus - E a tutte le altre risposte? –

+2

Penso che 'var arr = [101, 5, 6]' sia più semplice e più facile da leggere ... Sto solo dicendo. –

0

è necessario trovare il massimo e scalare tutti i numeri per il target di riferimento.

0
function normalize(arr, max) { 
    // find the max value 
    var m = 0; 
    for(var x=0; x<arr.length; x++) m = Math.max(m, arr[x]); 
    // find the ratio 
    var r = max/m; 
    // normalize the array 
    for(var x=0; x<arr.length; x++) arr[x] = arr[x] * r; 
    return arr; 
} 
0

Solo una modifica al codice LastCoder per supportare numeri negativi pure

function normalize(arr, max) { 
    // find the max value 
    var max = arr[0]; 
    var min = arr[0]; 
    for(var x=0; x<arr.length; x++) 
     max = Math.max(m, arr[x]; 
    for(var x=0; x<arr.length; x++) 
     min = Math.min(m, arr[x]; 

    // normalize the array 
    for(var x=0; x<arr.length; x++) 
     arr[x] = (arr[x] - min)/(max - min); 

    return arr; 
} 
Problemi correlati