Javascript计算值数组的百分比一致性

时间:2017-10-27 10:15:16

标签: javascript arrays algorithm percentage

我正在尝试计算输出百分比的值数组的一致性。因此,例如[1,1,1,1,1]的数组将输出100%的一致性,[1,12,23,5,2]的数组将输出类似25%的一致性。

我尝试了一个简单的百分比差异计算,但仅适用于两个数字,而这需要适用于动态数组,这只会输出差异。任何帮助将不胜感激,所以提前感谢。

function getPercentage(n1, n2){
   var newValue = n1 - n2;
   return (newValue / n1) * 100;
}
getPercentage(1, 12)

2 个答案:

答案 0 :(得分:1)

好的,这是我第一次尝试,尝试将其制作成更小的代码单元,以便更轻松地完成工作。如果我有足够的时间可以进一步完善,但随后可读性向南; - )

试图避免使用TypeScript并尽可能保持ECMAScript 5友好。 (抱歉格式混乱)

let ar100 = [1,1,1,1,1];
let ar25 = [1,12,23,5,2];

/**
 * Calculate the lack of difference between two values (ie consistency)
 * @param {number} valA
 * @param {number} valB
 * @returns {number} The consistency as a decimal
 *                  where 1 is '100% consistent'
 *                  and 0.5 is '50% consistent'
 */
var calcConsistency = function( valA, valB) {
    let diff = Math.abs(valA - valB);
    let consistency = (valA - diff) / valA;
    // assumption: you can't be less than zero consistent
    return consistency < 0 ? 0 : consistency;
}

/**
 * A predicate used by the map operation in 'overallConsistency'
 * @param {*} val
 * @param {*} index
 * @param {*} values
 * @return {number} the average consistency of the current 'val' to the other 'values'
 */
var mapEachConsistency = function(val, index, values) {
    let predicateGetOnlyOthers = function(currentValue, othersIndex) {
                                        return index !== othersIndex;
                                };

    let others = values.filter(predicateGetOnlyOthers);
    const otherCount = others.length;
    let totalConsistency = others.reduce(function(previousValue, currentValue) {
        return previousValue + calcConsistency(val, currentValue);
    });
    return (totalConsistency / otherCount);
}

/**
 * Calculate the overall average consistency of an array of numbers
 * @param {Array<number>} arrayOfValues
 * @return {number} The average consistency score as percentage
 */
var overallConsistency = function(arrayOfValues) {
    let consists = arrayOfValues.map(mapEachConsistency);

    let sumTotal = function(previous, current){ return previous + current; };

    let avgAnswer = consists.reduce(sumTotal);
    return (avgAnswer / consists.length) * 100;
};

// Here's using it to see the results
var answer = overallConsistency(ar100);
    console.log(`Consistency: ${answer.toFixed(3)}% (fixed to 3 dicimal place)`);

    answer = overallConsistency(ar25);
    console.log(`Consistency: ${answer.toFixed(3)}% (fixed to 3 dicimal place)`);

答案 1 :(得分:1)

根据您的评论,我改进了用于计算数组成员之间整体一致性的基值。

计算出的新结果(在视觉检查上似乎看似合理,再次取决于所有成员的一致性定义,但我认为这种情况越来越接近):

$ node jsscratch.js
Consistency for 1,1,1,1,1 is 100.000% fixed to 3 decimal places
Consistency for 1,12,23,5,2 is 33.360% fixed to 3 decimal places
Consistency for 1,12,23,15,12 is 50.160% fixed to 3 decimal places
Consistency for 1,2,10 is 83.778% fixed to 3 decimal places

/**
 * Calculate the expected value
 */
 function expectancy(arrayOfValues) {
    let sumTotal = function(previousValue, currentValue) { 
                         return previousValue + currentValue; 
                   };
    let u = arrayOfValues.reduce(sumTotal);
    // Assume each member carries an equal weight in expected value
    u = u / arrayOfValues.length;
    return u;
 }

 /**
  * Calculate consistency of the members in the vector
  * @param {Array<number>} The vector of members to inspect for similarity
  * @return {number} The percentage of members that are the same
  */
  var similarity = function(arrayOfValues) {
     let sumTotal = function(previousValue, currentValue) { 
                              return previousValue + currentValue; 
                    };
     // Step 1: Calculate the mean value u
     let u = expectancy(arrayOfValues); // Calculate the average
     // Step 2: Calculate the standard deviation sig
     let sig = [];
     let N = 1/arrayOfValues.length;

     for (let i = 0; i < arrayOfValues.length; i++) {
       sig.push(N*(arrayOfValues[i] - u) * (arrayOfValues[i] - u));
     }
     // This only works in mutable type, such as found in JavaScript, else sum it up
     sig = sig.reduce(sumTotal);
     // Step 3: Offset from 100% to get the similarity
     return 100 - sig;
    }

    answer = similarity(ar1);
    console.log(`Consistency for ${ar1} is ${answer.toFixed(3)}% fixed to 3 decimal places`);

    answer = similarity(ar2);
    console.log(`Consistency for ${ar2} is ${answer.toFixed(3)}% fixed to 3 decimal places`);

    answer = similarity(ar3);
    console.log(`Consistency for ${ar3} is ${answer.toFixed(3)}% fixed to 3 decimal places`);

    answer = similarity(ar4);
    console.log(`Consistency for ${ar4} is ${answer.toFixed(3)}% fixed to 3 decimal places`);