Deux fonctions utilitaires : méthode de solde maximum et limite de simultanéité

Aperçu

Les fonctions sont l'une des syntaxes les plus courantes en JavaScript et peuvent être utilisées pour encapsuler des fonctionnalités générales ou une logique métier.

Cet article présentera deux fonctions, l'une est la fonction correspondant à la méthode d'équilibre maximal et l'autre est la fonction de limite de concurrence asynchrone.

méthode du solde maximal

Lorsque j'écrivais récemment une entreprise de graphique à secteurs, j'ai constaté que le pourcentage du graphique à secteurs fourni par echarts est exactement de 100% lorsque deux décimales sont prises, mais si vous le calculez vous-même, il est fort probable que la somme ne soit pas 100 % en arrondissant. Tous allèrent étudier la méthode des écharts.

echarts utilise en interne la méthode du solde maximum pour calculer, jetons un coup d'œil à sa définition wiki .

La méthode du plus grand reste, également connue sous le nom de système de montant ou méthode de Hamilton, est une méthode d'attribution des sièges dans le cadre du système de vote à représentation proportionnelle.

Prenons l'exemple du wiki Supposons qu'il y ait 100 000 votes lors de l'élection et que 10 sièges soient attribués. Résultats des élections:

image.png

Pour 10 000 voix, vous pouvez obtenir 1 siège, et la liste en obtiendra 1. La liste a déjà attribué 4 sièges, comment répartir les 5 restants ? La méthode de distribution de la méthode du solde maximum consiste à distribuer dans l'ordre de la taille du solde, il y a donc 1 chacun pour Y (7000), B (6100), E (6000), D (5800) et A ( 6100) Jusqu'à présent, la distribution est complète.

image.png

Qu'est-ce que cela a à voir avec notre calcul des pourcentages ? Habituellement, nous pouvons utiliser des arrondis, ce qui fait que la somme des pourcentages n'est pas un pourcentage. Nous pouvons maintenant utiliser la méthode du solde maximal.

arrondi :

image.png

Nous supposons que le pourcentage est maintenu à deux décimales, alors les deux décimales sont équivalentes au solde, n'est-ce pas ? Calculons d'abord combien de "sièges" il y a actuellement, c'est-à-dire que la différence entre les valeurs après avoir arrondi deux décimales est de 100 %. Si la différence est de 0,02 %, nous répartirons les 0,02 % en fonction du solde de chaque élément. .

Méthode du solde maximum :

image.png

Ici on peut faire une optimisation, on s'assure que l'unité minimum du siège est 1, et on agrandit la part et le siège

image.png

Ensuite, implémentons-le. Laissez-moi d'abord trier les idées :

  1. Calculer le grossissement en fonction des décimales retenues
  2. Calculez le pourcentage de chaque élément du tableau, puis multipliez par 100 * l'échelle. À ce stade, la somme des éléments doit être de 100 * ratio (multiplié par 100, car le résultat de retour final est un pourcentage).
  3. Calculez séparément le siège actuel et le solde. La partie entière de chaque élément est le siège actuellement obtenu et la partie fractionnaire est le solde.
  4. Calculez le nombre de sièges non attribués et attribuez-les en fonction du solde maximal.
function getPercentWithPrecision(valueList, precision) {
  // 根据保留的小数位做对应的放大
  const digits = Math.pow(10, precision)
  const sum = valueList.reduce((total, cur) => total + cur, 0)
  
  // 计算每项占比,并做放大,保证整数部分就是当前获得的席位,小数部分就是余额
  const votesPerQuota = valueList.map((val) => {
      return val / sum * 100 * digits
  })
  // 整数部分就是每项首次分配的席位
  const seats = votesPerQuota.map((val) => {
    return Math.floor(val);
  });
  // 计算各项的余额
  const remainder = votesPerQuota.map((val) => {
    return val - Math.floor(val)
  })
    
  // 总席位
  const totalSeats = 100 * digits
  // 当前已经分配出去的席位总数
  let currentSeats = votesPerQuota.reduce((total, cur) => total + Math.floor(cur), 0)
    
  // 按最大余额法分配
  while(totalSeats - currentSeats > 0) {
    let maxIdx = -1 // 余数最大的 id
    let maxValue = Number.NEGATIVE_INFINITY // 最大余额, 初始重置为无穷小

    // 选出这组余额数据中最大值
    for(var i = 0; i < remainder.length; i++) {
      if (maxValue < remainder[i]) {
        maxValue = remainder[i]
        maxIdx = i
      }
    }
        
    // 对应的项席位加 1,余额清零,当前分配席位加 1
    seats[maxIdx]++
    remainder[maxIdx] = 0
    currentSeats++
  }
    
  return seats.map((val) => `${val / totalSeats * 100}%`)
}
复制代码

Jusqu'à présent, nous avons réalisé la méthode de l'équilibre maximal. Les étudiants intéressés peuvent consulter la méthode correspondante getPercentWithPrecision dans echarts, qui est fondamentalement la même.

Limite de simultanéité asynchrone

La fonction de limitation de la concurrence asynchrone est également très courante. Si un groupe de requêtes est émis en même temps, le réseau peut être occupé par ce groupe de requêtes, et d'autres requêtes seront classées derrière, nous voulons donc limiter le nombre de demandes concurrentes.

Ici, nous regardons directement l'implémentation de async-pool-tiny

async function asyncPool(poolLimit, iterable, iteratorFn) {
  // 用于保存所有异步请求
  const ret = [];
  // 用户保存正在进行的请求
  const executing = new Set();
  for (const item of iterable) {
    // 构造出请求 Promise
    const p = Promise.resolve().then(() => iteratorFn(item, iterable));
    ret.push(p);
    executing.add(p);
    // 请求执行结束后从正在进行的数组中移除
    const clean = () => executing.delete(p);
    p.then(clean).catch(clean);
    // 如果正在执行的请求数大于并发数,就使用 Promise.race 等待一个最快执行完的请求
    if (executing.size >= poolLimit) {
      await Promise.race(executing);
    }
  }
  // 返回所有结果
  return Promise.all(ret);
}

// 使用方法
const timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
asyncPool(2, [1000, 5000, 3000, 2000], timeout).then(results => {
  console.log(results)
})
复制代码

L'implémentation principale consiste à utiliser Promise.race et Promise.all. Si le nombre de requêtes émises est supérieur au nombre de requêtes simultanées, la requête suivante ne sera pas lancée à ce moment, mais Promise.race sera utilisé pour attendre une requête avec la fin d'exécution la plus rapide, puis continuer à envoyer le demande. Enfin, retournez toutes les extrémités via Promise.all.

Résumer

L'implémentation de la méthode d'équilibre maximal et d'asyncPool est très intelligente, le code est élégant et vaut la peine d'être appris. Avez-vous des fonctions utiles à recommander et à apprendre les uns des autres.

Je suppose que tu aimes

Origine juejin.im/post/7078532391832125448
conseillé
Classement