2012-11-13 16 views
5

Mam tablicę wypełnioną dodatnimi wartościami int, w jaki sposób mogę znormalizować tę listę, aby maksymalna wartość wynosiła zawsze 100? Z góry dziękuję!Jak znormalizować listę liczb dodatnich w JavaScript?

+4

[Co próbowaliście?] (http://whathaveyoutried.com/) – ruakh

+0

Bardziej szczegółowe. Co robisz z wartościami? pomnożyć/pozbyć się ich? Czy jesteś po procentowej proporcji? –

+2

Będziesz musiał być trochę bardziej konkretny, tutaj. Jeśli *** poddajesz normalizacji wartości ***, aby maksymalna wartość została zmniejszona do wartości równej dokładnie 100, wówczas zastosowanie tej skali do wszystkich pozostałych liczb jest *** NIE *** pozostawi je jako liczby całkowite. Czy chcesz uzyskać najwyższą skalę liczb do dokładnie 100, nawet jeśli będziesz miał pływaki, czy też chcesz odrzucić liczby wyższe niż 100 (filtr) lub zablokować wszystkie liczby większe od 100 do równych 100 i pozostawić odpoczywać samotnie (zniekształcając skalę), czy próbujesz zrobić coś innego? – Norguard

Odpowiedz

21

Chodzi o to, aby najpierw znaleźć największą liczbę w macierzy (używając apply na Math.max), a następnie znaleźć proporcje między tym najwyższą liczbę i 100.

potem, że to tylko kwestia zapętlenie za pośrednictwem tablicy i dzieląc wszystkie swoje numery od tego wskaźnika:

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); 
} 

Oto skrzypce: http://jsfiddle.net/XpRR8/


Uwaga: Używam Math.round do zaokrąglania liczb do najbliższej liczby całkowitej. Jeśli zamiast tego wolą trzymać je jako pływaków, po prostu usunąć wywołanie funkcji:

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

Oto skrzypce: http://jsfiddle.net/XpRR8/1/


jeśli nie masz do wspierania IE8 i poniżej, można użyć 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); 
}); 

Oto skrzypce: http://jsfiddle.net/XpRR8/2/


Jeśli zrobić support IE8, ale tak czy owak przy użyciu jQuery, można użyć $.map() zamiast:

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

Oto skrzypce: http://jsfiddle.net/XpRR8/3/


Aktualizacja: Jak wskazano przez @wvxvw w komentarzach poniżej, jeśli martwisz się wprowadzaniem ograniczeń nakładających sztuczne ograniczenie liczby argumentów: apply obsłuży, a następnie użyje pętli zamiast Math.max.apply.Oto przykład (zakładając, ani Array.prototype.map ani $.map są dostępne):

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); 

oto skrzypce: http://jsfiddle.net/XpRR8/4/


Jeśli używasz ES6, to staje się śmiesznie proste:

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

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

+1 w celu uzyskania szczegółowej odpowiedzi. – Shmiddty

+0

@wvxvw - Interesujące. [Tutaj jest test używający 'apply' z 10 000 elementów] (http://jsfiddle.net/9HXv4/) i działa bezbłędnie we wszystkich głównych przeglądarkach; Testowałem go nawet w 5 najnowszych przeglądarkach IE (6-10). Bycie tym [różnica w wydajności wydaje się skłaniać do "zastosowania"] (http://jsperf.com/math-max-apply-vs-loop), (aw IE <9 różnica jest * oszałamiająca *), I "sugeruj trzymanie się z" zastosuj ". (Nota boczna: Firefox wydaje się używać jakiegoś szalonego voodoo, aby osiągnąć nieprawidłową wydajność z metody pętli. –

+0

@wvxvw - Chociaż masz rację, że moja implementacja pętli nie była najskuteczniejsza, użycie pętli nie zmienia zbyt wiele obrazu: starsze wersje IE (gdzie, prawdopodobnie, te optymalizacje są najbardziej potrzebne) nadal faworyzują 'apply 'przez * duży * margines. –

0

Cóż, możesz uzyskać maksymalną wartość za pomocą Math.max.apply(arr), a następnie przepuścić lub użyć arr.map, aby pomnożyć wszystkie liczby przez 100/max. Gotowe.

4

Ci się to

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

a następnie użyć go:

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

Szanuję, że próbujesz pomóc, ale po prostu ktoś im pomógł. : [Dla zapisu nie byłem -1. – Snuffleupagus

+0

@Snuffleupagus - I do wszystkich innych odpowiedzi? –

+2

Myślę, że 'var arr = [101, 5, 6]' jest prostsze i łatwiejsze do odczytania ... Po prostu mówię. –

0

Trzeba znaleźć maksimum i skalować wszystkie numery do zakresu docelowego.

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

Wystarczy edytować kod LastCoder, aby obsługiwać numery ujemne a także

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; 
} 
Powiązane problemy