【问题标题】:Javascript calculate percentage consistency of an array of valuesJavascript计算值数组的百分比一致性
【发布时间】:2018-04-08 22:06:23
【问题描述】:

我正在尝试计算输出百分比的值数组的一致性。例如,[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)

【问题讨论】:

  • [1,12,23,5,2] 的数组会输出类似 25% 的一致性。 你能解释一下 25% 背后的计算吗?
  • 您好,这只是一个猜测值作为示例,很抱歉造成混淆。
  • 那你需要什么帮助?
  • 我需要计算任何值数组之间的一致性百分比。那么如果一个数组包含 [1,5,8,12,2,18] 所有这些值的一致性是什么?即如果数组是 [2,2,2,2,2,2],它将是 100% 的一致性。

标签: javascript arrays algorithm percentage


【解决方案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)`);

【讨论】:

  • 你有什么问题?
  • @AlexandreDupriez 我不认为马吕斯有问题,因为他正在为这个人的问题提供他的解决方案。
  • @Matt Ooops - 我的错 :-) 对不起。
  • 您好 Marius,感谢您的解决方案。我只需要从一个数组 [1,12,23,15,12] 开始工作,因此比较只是每个值与另一个值的比较。 [1,1,1,1,1] 的数组只是为了表明它将输出 100% 的一致性。目前 [1,12,23,15,12] 的数组输出 '117.145%' 但应该小于百分比,因为这些数字彼此之间不是很一致。希望这对您有所帮助并感谢您的宝贵时间。
  • 嘿@dbach 没错,上面的示例测试了两个示例数组。我对一致性的定义做了一些假设……我认为这是一个起点(一旦原型正确,它就可以汇总为一系列 map+reduce 调用)。导致非标准化答案的新示例表明数学的汇总阶段不正确。也许使用最终的归一化总数作为更具数值意义的基值会解决它)...
【解决方案2】:

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

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

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

【讨论】:

  • 如果一致性被量化描述为所有成员之间的相关性,那么上述算法的汇总阶段将需要稍微调整。
  • 是的,这更接近了,谢谢,我猜一致性的定义很困难,并且随着数组的变化和增长将基于所有成员。所以如果数组是: [1] 输出 = 100% [1,1] = 100% [1,2] = 50% [1,2,10] = ? (我猜是 25% 或更低?!)
  • 如果我可以问一下您要解决的这个应用程序是什么?高级概念可能会导致为其推理更好的数学模型,一旦将高级概念转换为可量化格式的模型从合格的概念(高级概念)导出,实际算法就可以直接设计。 .
  • 嗨,Marius,它只是对比赛进行时收集的分数的统计。因此,如果分数非常接近,则统计百分比会更高,否则百分比会更低。
  • 嘿@dbach 在这种情况下,它更像是您正在寻找的相关算法。因此,第二次修订的算法接近但不正确。示例:[1, 12, 23, 15, 12] 应该在 3 个成员的球场范围内,在 5 个成员中非常接近,因此预计答案接近 60%...
猜你喜欢
  • 2021-12-09
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多