根据范围中的数字查找字符串

时间:2016-11-23 21:45:39

标签: python python-3.x lookup-tables

我正在尝试为我的游戏小组创建一个排名系统,在他们的Clash of Clans和Clash Royale游戏的Android / iOS系统中与Supercell的Trophy System类似。

我已经找到了所有排名的布局,我们已经有一个适用的点系统......我只需要在实际排名中进行编程。

排名非常简单:个人的积分余额属于特定值,与该值对应的排名是该人的排名。我创建了一个简单的表来显示我的意思...这里是它的外观摘录:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    text {
      fill: black;
      font-family: arial;
    }
  </style>
</head>

<body>
  <script>
    var dataNodes = [{
      id: 1,
      x: 10,
      y: 30,
      text: "node 1",
      muteText: false
    }, {
      id: 2,
      x: 30,
      y: 50,
      text: "node 2",
      muteText: false
    }, {
      id: 3,
      x: 50,
      y: 70,
      text: "node 3",
      muteText: false
    }];

    var svg = d3.select('body')
      .append('svg')
      .attr('width', 500)
      .attr('height', 500);

    redraw([{
        id: 1,
        x: 10,
        y: 30,
        text: "node 1",
        muteText: false
      }, {
        id: 2,
        x: 30,
        y: 50,
        text: "node 2",
        muteText: false
      }, {
        id: 3,
        x: 50,
        y: 70,
        text: "node 3",
        muteText: false
      }]);
    
    setTimeout(function() {
      redraw([{
        id: 1,
        x: 10,
        y: 30,
        text: "node 1",
        muteText: true
      }, {
        id: 2,
        x: 100,
        y: 50,
        text: "node 2",
        muteText: false
      }, {
        id: 3,
        x: 50,
        y: 70,
        text: "node 3",
        muteText: true
      }])
    }, 2000)
    
    setTimeout(function() {
      redraw([{
        id: 1,
        x: 10,
        y: 30,
        text: "node 1",
        muteText: true
      }, {
        id: 2,
        x: 100,
        y: 50,
        text: "node 2",
        muteText: false
      }, {
        id: 3,
        x: 50,
        y: 70,
        text: "node 3",
        muteText: false
      },{
        id: 4,
        x: 60,
        y: 90,
        text: "node 4",
        muteText: false
      }])
    }, 4000)

    function redraw(someData) {

      var node = svg
        .selectAll("g.node")
        .data(someData);

      var nodeE = node.enter()
        .append("g")
        .attr("class", "node")
        .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

      nodeE.append("text")
        .text(d => d.text)
        .style("opacity", 0)
        .transition()
        .style("opacity", 1);

      node = nodeE.merge(node);

      node.exit()
        .style("opacity", "0");

      node.transition().duration(500)
        .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

      node.filter(function(d) {
          return d.muteText
        })
        .select("text")
        .transition()
        .style("opacity", 0);    

    }
  </script>
</body>

</html>

所以这里是简单的等级系统布局,它一直到Commander的42,000点。我的问题是:如何将Rank与点值相关联,而不必像这样输入所有代码行?

Rank: Balance Range
Private: 0-500
Private I: 501-1000
Private II: 1001-1500
Private III: 1501-2500
Corporal: 2501-3000
...

2 个答案:

答案 0 :(得分:1)

您可以使用bisect

from bisect import bisect
def get_rank(score):
    points = [500, 1000, 1500, 2500, 3000]
    ranks = ["Private", "Private I", "Private II", "Private III", "Corporal"]
    div = bisect(points, score)
    return ranks[div]

答案 1 :(得分:0)

丹尼尔罗斯曼的bisect解决方案略有改进,将使用单个2元组列表:

from bisect import bisect_right

RANKS = [
    # max balance, rank
    (500, 'Private'),
    (1000, 'Private I'),
    (1500, 'Private II'),
    (2500, 'Private III'),
    (3000, 'Corporal'),
    # ...
    (42000, 'Commander')
]

def get_rank(balance):
    index = bisect_right(RANKS, (balance, ''))
    try:
        return RANKS[index][1]
    except IndexError:
        return RANKS[-1][1]

这里的优点是一目了然更容易阅读,并且在编辑代码以引入新等级,调整限制等时更不容​​易出错。

当提供的分数余额高于RANKS(在评论中指定)中的任何分数时,它也会返回最高排名,而非提出异常。

示例:

>>> for n in range(0,42001,500):
...     print("%5d  %s" % (n, get_rank(n)))
...     print("%5d  %s" % (n + 1, get_rank(n + 1)))
... 
    0  Private
    1  Private
  500  Private
  501  Private I
 1000  Private I
 1001  Private II
 1500  Private II
 1501  Private III
 2000  Private III
 2001  Private III
 2500  Private III
 2501  Corporal
 3000  Corporal
 # ...
 42000  Commander
 42001  Commander