web-dev-qa-db-fra.com

Somme de tableau et moyenne

J'ai des problèmes pour ajouter tous les éléments d'un tableau ainsi que pour les faire la moyenne. Comment pourrais-je faire cela et le mettre en œuvre avec le code que j'ai actuellement? Les éléments sont supposés être définis comme ci-dessous. 

<script type="text/javascript">
//<![CDATA[

var i;
var elmt = new Array();

elmt[0] = "0";
elmt[1] = "1";
elmt[2] = "2";
elmt[3] = "3";
elmt[4] = "4";
elmt[5] = "7";
elmt[6] = "8";
elmt[7] = "9";
elmt[8] = "10";
elmt[9] = "11";

// problem here
for (i = 9; i < 10; i++)
{
    document.write("The sum of all the elements is: " + /* problem here */ + " The average of all the elements is: " + /* problem here */ + "<br/>");
}   

//]]>
</script>
121
jonathan miller
var sum = 0;
for( var i = 0; i < elmt.length; i++ ){
    sum += parseInt( elmt[i], 10 ); //don't forget to add the base
}

var avg = sum/elmt.length;

document.write( "The sum of all the elements is: " + sum + " The average is: " + avg );

Il suffit de parcourir le tableau, puisque vos valeurs sont des chaînes, elles doivent d'abord être converties en un entier. Et la moyenne est simplement la somme des valeurs divisée par le nombre de valeurs.

105
Marcus Recck

Une solution que je considère plus élégante:

var sum, avg = 0;

// dividing by 0 will return Infinity
// arr must contain at least 1 element to use reduce
if (arr.length)
{
    sum = arr.reduce(function(a, b) { return a + b; });
    avg = sum / arr.length;
}

document.write("The sum is: " + sum + ". The average is: " + avg + "<br/>");
414
Sergi Mansilla

ES6

const average = arr => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
    
const result = average( [ 4, 4, 5, 6, 6 ] ); // 5
    
console.log(result);

67
Abdennour TOUMI

généralement moyen en utilisant one-liner réduire est comme ça

elements.reduce(function(sum, a,i,ar) { sum += a;  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

spécifiquement à la question posée

elements.reduce(function(sum, a,i,ar) { sum += parseFloat(a);  return i==ar.length-1?(ar.length==0?0:sum/ar.length):sum},0);

une version efficace est comme

elements.reduce(function(sum, a) { return sum + a },0)/(elements.length||1);

Comprendre le tableau Javascript réduire en 1 minute http://www.airpair.com/javascript/javascript-array-reduce

comme gotofritz l'a fait remarquer, Array.reduce saute des valeurs indéfinies . Voici donc un correctif:

(function average(arr){var finalstate=arr.reduce(function(state,a) { state.sum+=a;state.count+=1; return state },{sum:0,count:0}); return finalstate.sum/finalstate.count})([2,,,6])
20
Shimon Doodkin

Imaginons que nous ayons un tableau d'entiers comme celui-ci:

var values = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

La moyenne est obtenue avec la formule suivante

A = (1/n) Σxi(avec i = 1 à n) ... Donc: x1/n + x2/n + ... + xn/n

Nous divisons la valeur actuelle par le nombre de valeurs et ajoutons le résultat précédent à la valeur renvoyée.

La signature de la méthode de réduction est 

reduce(callback[,default_previous_value])

La fonction de rappel réduit prend les paramètres suivants:

  • p: Résultat .__ du calcul précédent 
  • c: valeur actuelle (à partir de l'index actuel)
  • i: valeur d'index de l'élément de tableau actuel
  • a: Le tableau actuel réduit

Le second paramètre de réduction est le valeur par défaut} ... ... (utilisé dans le cas où le tableau est vide).

La méthode de réduction moyenne sera donc:

var avg = values.reduce(function(p,c,i,a){return p + (c/a.length)},0);

Si vous préférez, vous pouvez créer une fonction séparée 

function average(p,c,i,a){return p + (c/a.length)};
function sum(p,c){return p + c)};

Et puis simplement faire référence à la signature de la méthode de rappel 

var avg = values.reduce(average,0);
var sum= values.reduce(sum,0);

Ou augmentez directement le prototype de tableau. 

Array.prototype.sum = Array.prototype.sum || function (){
  return this.reduce(function(p,c){return p+c},0);
};

Il est possible de diviser la valeur chaque fois que la méthode de réduction est appelée. 

Array.prototype.avg = Array.prototype.avg || function () {
  return this.reduce(function(p,c,i,a){return p+(c/a.length)},0);
};

Ou encore mieux, en utilisant le défini précédemmentArray.protoype.sum ()

méthode, optimisez le processus en appelant la division une seule fois :)

Array.prototype.avg = Array.prototype.avg || function () {
  return this.sum()/this.length; 
};

Puis sur n'importe quel objet Array de la portée:

[2, 6].avg();// -> 4
[2, 6].sum();// -> 8

NB: un tableau vide avec le retour d'un souhait NaN est plus correct que 0 selon mon point de vue et peut être utile dans des cas d'utilisation spécifiques.

14
Ludovic Frérot

Calculer la moyenne (moyenne) en utilisant réduire et ES6:

const average = list => list.reduce((prev, curr) => prev + curr) / list.length;

const list = [0, 10, 20, 30]
average(list) // 15
12
Tomasz Mularczyk

Vous pouvez également utiliser lodash , _.sum (tableau) et _.mean (tableau) dans la partie mathématique (également disposer d’un autre personnel pratique).

_.sum([4, 2, 8, 6]);
// => 20
_.mean([4, 2, 8, 6]);
// => 5
8
Geng Jiawen

Pas le plus rapide, mais le plus court et sur une seule ligne utilise map () & reduction ():

var average = [7,14,21].map(function(x,i,arr){return x/arr.length}).reduce(function(a,b){return a + b})
6
Johann Echavarria

Dans ES6-ready navigateurs, ce polyfill peut être utile.

Math.sum = (...a) => Array.prototype.reduce.call(a,(a,b) => a+b)

Math.avg = (...a) => this.sum(...a)/a.length;

Vous pouvez partager la même méthode d’appel entre Math.sum, Math.avg et Math.max, telle que

var maxOne = Math.max(1,2,3,4) // 4;

vous pouvez utiliser Math.sum comme

var sumNum = Math.sum(1,2,3,4) // 10

ou si vous avez un tableau à résumer, vous pouvez utiliser 

var sumNum = Math.sum.apply(null,[1,2,3,4]) // 10

juste comme 

var maxOne = Math.max.apply(null,[1,2,3,4]) // 4
4
Oboo Chin

Une façon sournoise de le faire, même si cela nécessite l’utilisation de (très détesté) eval ().

var sum = eval(elmt.join('+')), avg = sum / elmt.length;
document.write("The sum of all the elements is: " + sum + " The average of all the elements is: " + avg + "<br/>");

Je pensais que je posterais ceci comme une de ces options "hors des sentiers battus". Vous ne savez jamais, la sournoiserie peut vous accorder (ou retirer) un point.

4
Phil Cooper

J'utilise ces méthodes dans ma bibliothèque personnelle:

Array.prototype.sum = Array.prototype.sum || function() {
  return this.reduce(function(sum, a) { return sum + Number(a) }, 0);
}

Array.prototype.average = Array.prototype.average || function() {
  return this.sum() / (this.length || 1);
}

EDIT: Pour les utiliser, il suffit de demander au tableau sa somme ou sa moyenne, comme ceci:

[1,2,3].sum() // = 6
[1,2,3].average() // = 2
4
Keith

Voici un ajout rapide à l'objet "Math" en javascript pour lui ajouter une commande "moyenne" !!

Math.average = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output/input.length;
}

Ensuite, j'ai cet ajout à l'objet «Math» pour obtenir la somme!

Math.sum = function(input) {
  this.output = 0;
  for (this.i = 0; this.i < input.length; this.i++) {
    this.output+=Number(input[this.i]);
  }
  return this.output;
}

Alors tout ce que vous faites est

alert(Math.sum([5,5,5])); //alerts “15”
alert(Math.average([10,0,5])); //alerts “5”

Et où je mets le tableau de marque de réservation il suffit de passer votre variable (L'entrée si elles sont des nombres peut être une chaîne à cause de son analyse d'un nombre!)

3
Jacob Morris

Si quelqu'un en a besoin - Voici une moyenne récursive. 

Dans le contexte de la question initiale, vous pouvez utiliser la moyenne récursive si vous autorisez l'utilisateur à insérer des valeurs supplémentaires et, sans engager le coût de la visite de chaque élément, si vous souhaitez "mettre à jour" la moyenne existante. 

/**
 * Computes the recursive average of an indefinite set
 * @param {Iterable<number>} set iterable sequence to average
 * @param {number} initAvg initial average value
 * @param {number} initCount initial average count
 */
function average(set, initAvg, initCount) {
  if (!set || !set[Symbol.iterator])
    throw Error("must pass an iterable sequence");

  let avg = initAvg || 0;
  let avgCnt = initCount || 0;
  for (let x of set) {
    avgCnt += 1;
    avg = avg * ((avgCnt - 1) / avgCnt) + x / avgCnt;
  }
  return avg; // or {avg: avg, count: avgCnt};
}

average([2, 4, 6]);    //returns 4
average([4, 6], 2, 1); //returns 4
average([6], 3, 2);    //returns 4
average({
  *[Symbol.iterator]() {
    yield 2; yield 4; yield 6;
  }
});                    //returns 4

Comment: 

cela fonctionne en maintenant la moyenne actuelle et le nombre d'éléments. Lorsqu'une nouvelle valeur doit être incluse, vous incrémentez le nombre d'un, redimensionnez la moyenne existante de (count-1) / count et ajoutez newValue / count à la moyenne. 

Avantages: 

  • vous ne faites pas la somme de tous les éléments, ce qui peut entraîner un grand nombre de données qui ne peuvent pas être stockées dans un fichier float de 64 bits. 
  • vous pouvez "mettre à jour" une moyenne existante si des valeurs supplémentaires deviennent disponibles. 
  • vous pouvez effectuer une moyenne glissante sans connaître la longueur de la séquence. 

Inconvénients: 

  • encourt beaucoup plus de divisions
  • not infinite - limité à Number.MAX_SAFE_INTEGER, sauf si vous utilisez BigNumber
1
Meirion Hughes

Sur les navigateurs permanents, vous pouvez utiliser les fonctions de flèche avg = [1,2,3].reduce((a,b) => (a+b);

100 000 fois, la différence de temps entre l’approche en boucle et la réduction est négligeable.

s=Date.now();for(i=0;i<100000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("100k reduce took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<100000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("100k for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){n=[1,2,3]; nl=n.length; a=0; for(j=nl-1;j>0;j--){a=a+n[j];} a/nl };
console.log("1M for loop took " + (Date.now()-s) + "ms.");

s=Date.now();for(i=0;i<1000000;i++){ n=[1,2,3]; a=n.reduce((a,b) => (a+b)) / n.length };
console.log("1M reduce took " + (Date.now()-s) + "ms.");

/* 
 * RESULT on Chrome 51
 * 100k reduce took 26ms.
 * 100k for loop took 35ms.
 * 10M for loop took 126ms.
 * 10M reduce took 209ms.
 */

1
Ray Foss

mettez votre compteur de boucles for à 0 .... vous obtenez l’élément 9 et vous avez terminé tel que vous l’avez maintenant. Les autres réponses sont des mathématiques de base. Utilisez une variable pour stocker votre somme (nécessité de convertir les chaînes en ints) et divisez-la par la longueur de votre tableau.

1
Volvox

Commencez par définir toutes les variables que nous prévoyons d'utiliser. Vous remarquerez que pour le tableau numbers, j'utilise la notation littérale [], par opposition à la méthode constructeur array(). De plus, j'utilise une méthode plus courte pour définir plusieurs variables à 0.

var numbers = [], count = sum = avg = 0;

Ensuite, je remplis mon tableau de nombres vides avec les valeurs de 0 à 11. Cela me permet de revenir à votre point de départ d'origine. Notez comment je pousse sur le tableau count++. Cette poussée de la valeur actuelle du compte, puis incrémente pour la prochaine fois.

while ( count < 12 )
    numbers.Push( count++ );

Enfin, j'exécute une fonction "pour chaque" des nombres dans le tableau des nombres. Cette fonction gérera un numéro à la fois, que j'identifie comme "n" dans le corps de la fonction.

numbers.forEach(function(n){
  sum += n; 
  avg = sum / numbers.length;
});

En fin de compte, nous pouvons exporter la valeur sum et la valeur avg sur notre console afin d'afficher le résultat:

// Sum: 66, Avg: 5.5
console.log( 'Sum: ' + sum + ', Avg: ' + avg );

Voyez-le en action en ligne à http://jsbin.com/unukoj/3/edit

1
Sampson

Je ne fais que construire la réponse d'Abdennour TOUMI. voici les raisons pour lesquelles:

1.) Je suis d'accord avec Brad, je ne pense pas que ce soit une bonne idée d'étendre un objet que nous n'avons pas créé.

2.) array.length est exactement fiable en javascript, je préfère Array.reduce car a=[1,3];a[1000]=5;, maintenant a.length renverrait 1001.

function getAverage(arry){
    // check if array
    if(!(Object.prototype.toString.call(arry) === '[object Array]')){
        return 0;
    }
    var sum = 0, count = 0; 
    sum = arry.reduce(function(previousValue, currentValue, index, array) {
        if(isFinite(currentValue)){
            count++;
            return previousValue+ parseFloat(currentValue);
        }
        return previousValue;
    }, sum);
    return count ? sum / count : 0; 
};
1
mido
protected void Submit_Click(object sender, EventArgs e)
{
    foreach (ComputerLabReservationList row in db.ComputerLabReservationLists)
    {
        if (row.LabNo == lblLabNo.Text && row.ReservationDate == StartCld.Text && row.StartEndTime == ddlstartendtime.Text)
        {
            // string display = "This time have been reserved by others. Please reserve again.";
            // ClientScript.RegisterStartupScript(this.GetType(), "yourMessage", "alert('" + display + "');", true);
            ScriptManager.RegisterStartupScript(this, this.GetType(),
            "alert",
            "alert('This time already booked by other. Please insert another time');window.location ='Computerlabs.aspx';",
                  true);
        }
        else
        {
            ComputerLabReservationList crl = new ComputerLabReservationList()
            {
                ResvId = lblreservationid.Text,
                LabNo = lblLabNo.Text,
                LecturerId = lblLecturerID.Text,
                ReservationDate = StartCld.Text,
                StartEndTime = ddlstartendtime.Text
            };
            db.ComputerLabReservationLists.InsertOnSubmit(crl);
            db.SubmitChanges();
            ScriptManager.RegisterStartupScript(this, this.GetType(),
            "alert",
            "alert('Your Reservation was sucessfully');window.location ='MyComputerReservation.aspx';",
            true);                    
        }
    }
}
0
Tan Sze Yuan

Juste pour le plaisir:

var elmt = [0, 1, 2,3, 4, 7, 8, 9, 10, 11], l = elmt.length, i = -1, sum = 0;
for (; ++i < l; sum += elmt[i])
    ;
document.body.appendChild(document.createTextNode('The sum of all the elements is: ' + sum + ' The average of all the elements is: ' + (sum / l)));
0
user1720624

Si vous avez besoin de la moyenne et pouvez ignorer l'obligation de calculer la somme, vous pouvez calculer la moyenne avec un seul appel de réduction:

// Assumes an array with only values that can be parsed to a Float
var reducer = function(cumulativeAverage, currentValue, currentIndex) {
  // 1. multiply average by currentIndex to find cumulative sum of previous elements
  // 2. add currentValue to get cumulative sum, including current element
  // 3. divide by total number of elements, including current element (zero-based index + 1)
  return (cumulativeAverage * currentIndex + parseFloat(currentValue))/(currentIndex + 1)
}
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce(reducer, 0)); // => 5.5
console.log([].reduce(reducer, 0)); // => 0
console.log([0].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0
console.log([,,,].reduce(reducer, 0)); // => 0
console.log([].reduce(reducer, 0)); // => 0
0
sealocal

voici votre un paquebot:

var average = arr.reduce((sum,item,index,arr)=>index !== arr.length-1?sum+item:sum+item/arr.length,0)
0
Alex C.

Je pense qu'on peut faire comme

var k=elmt.reduce(function(a,b){return parseFloat(a+parseFloat(b));})
var avg=k/elmt.length; 
console.log(avg);

J'utilise parseFloat deux fois parce que Quand 1) vous ajoutez un nombre (a) 9 + b ("1"), alors le résultat sera "91" mais nous voulons en ajouter. donc j'ai utilisé parseFloat

2) Lorsque l'addition de (a) 9 + parseFloat ("1") se produit, le résultat sera "10" mais ce sera dans une chaîne que nous ne voulons pas. J'ai donc utilisé parseFloat.

J'espère que je suis clair. Les suggestions sont les bienvenues 

0
Roli Agrawal

Il semble y avoir un nombre infini de solutions pour cela, mais j’ai trouvé cela concis et élégant.

const numbers = [1,2,3,4];
const count = numbers.length;
const reducer = (adder, value) => (adder + value);
const average = numbers.map(x => x/count).reduce(reducer);
console.log(average); // 2.5

Ou plus consciemment:

const numbers = [1,2,3,4];
const average = numbers.map(x => x/numbers.length).reduce((adder, value) => (adder + value));
console.log(average); // 2.5

Selon votre navigateur, vous devrez peut-être faire des appels de fonction explicites car les fonctions de flèche ne sont pas prises en charge:

const r = function (adder, value) {
        return adder + value;
};
const m = function (x) {
        return x/count;
};
const average = numbers.map(m).reduce(r);
console.log(average); // 2.5

Ou:

const average1 = numbers
    .map(function (x) {
        return x/count;
     })
    .reduce(function (adder, value) {
        return adder + value;
});
console.log(average1);
0
Charles Owen
Array.prototype.avg=function(fn){
    fn =fn || function(e,i){return e};
    return (this.map(fn).reduce(function(a,b){return parseFloat(a)+parseFloat(b)},0) / this.length ) ; 
};

Ensuite : 

[ 1 , 2 , 3].avg() ;  //-> OUT : 2

[{age:25},{age:26},{age:27}].avg(function(e){return e.age}); // OUT : 26
0
Abdennour TOUMI

Voici ma façon novatrice de trouver simplement le moyen. J'espère que ça aide quelqu'un.

function numAvg(num){
    var total = 0;
    for(var i = 0;i < num.length; i++) { 
        total+=num[i];
    }
    return total/num.length;
}
0
Jeremiah

Je pense que cela peut être une solution directe pour calculer la moyenne avec une boucle et une fonction.

var elmts = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

function average(arr) {
    var total = 0;
    for (var i = 0; i < arr.length; i++) {
        total += arr[i];
    }
        console.log(Math.round(total/arr.length));
}

average(elmts);
0
redcoder