使用Javascript数组

时间:2017-03-08 10:30:34

标签: javascript arrays

我有一个二维数组,如下所示:

let electionResultsData = [
    ["VVD", "vvd", 20.5, 2504948],
    ["PVDA", "pvda", 19.6, 2340750],
    ["PVV", "pvv", 15.4, 950263],
    ["CDA", "cda", 13.6, 801620],
    ["SP", "sp", 9.8, 909853],
    ["D66", "d66", 6.9, 757091],
    ["GL", "gl", 6.7, 219896],
    ["CU", "cu", 3.2, 294586],
    ["SGP", "sgp", 1.7, 196780],
    ["PVDD", "pvdd", 1.3, 182162],
    ["50PLUS", "50plus", 0.9, 177631],
    ["OVERIG", "overig", 0.2, 51463],
    ["PIRATEN", "piraten", 0.1, 30600],
    ["LP", "lp", 0.1, 3335],
    ["PVDM", "pvdm", 0.1, 3257],
    ["JEZUSLFT", "jezuslft", 0, 0],
    ["ONDRNMR", "ondrnmr", 0, 0],
    ["LOKAAL", "lokaal", 0, 0],
    ["ARTIKEL1", "artikel1", 0, 0],
    ["GEENPEIL", "geenpeil", 0, 0],
    ["VRIJP", "vrijp", 0, 0],
    ["BURGBEW", "burgbew", 0, 0],
    ["FVD", "fvd", 0, 0],
    ["VDP", "vdp", 0, 0],
    ["NIEUWEW", "nieuwew", 0, 0],
    ["DENK", "denk", 0, 0],
    ["STEMNL", "stemnl", 0, 0],
    ["VNL", "vnl", 0, 0]
]

每个数组中的第一个值是政党的大写名称,第二个值是小写名称,第三个值是投票百分比,第四个值是投票数。仅供参考,这些是荷兰政党。

我现在要做的是建立一个计算可能联盟的系统。只有当事方在议会中获得超过75个席位(至少76个席位),才能实现政党之间的联盟。我用这段代码做了一个循环遍历上面的数组:

/**
 * Form coalitions of not more than six parties that exceed 75 parliament seats
 */
formCoalitions(electionResultsData) {
    let coalitions = [];
    let maxNumberOfCoalitionParties = 6;

    // Main loop to check all possible coalitions (28 parties * 28 = 784)
    for (let i = 0; i < 784; i ++) {
        let coalitionSeats = 0;
        let partySeats = 0;
        let coalitionParties = [];
        let coalition = [];

        // The inner loop to generate a combination/coalition
        for (let i = 0; i < electionResultsData.length; i++) {
            // Check if a coalition has formed yet
            if (coalitionSeats < 76) {
                partySeats = (150 / 100) * electionResultsData[i][2];
                coalitionSeats += partySeats;
                coalitionParties.push(electionResultsData[i][0]);

                // If coalition has formed
                if (coalitionSeats > 75) {
                    // Push data into a second dimension coalition array
                    coalition[0] = parseInt(coalitionSeats);
                    coalition[1] = coalitionParties;

                    // Check if the generated coalition array already exists
                    let coalitionsStringified = JSON.stringify(coalitions);
                    let coalitionStringified = JSON.stringify(coalition);
                    let coalitionExists = coalitionsStringified.indexOf(coalitionStringified);

                    if (coalitionExists === -1) {
                        coalitions.push(coalition);
                    }
                }
            }
        }
    }

    // Loop through the coalitions (the charts will be drawn here)
    for (let i = 0; i < coalitions.length; i++) {
        console.log(coalitions[i]);
    }
}

问题是,这段代码只产生了一个可能的联盟,而不是所有可能的联盟。我需要以某种方式存储已生成的组合并再次运行循环而不生成相同的联盟。循环必须继续这样做,直到生成了不超过六方的所有可能的联盟。之后,循环可以停止。

最好的方法是什么?

2 个答案:

答案 0 :(得分:8)

我提出以下建议。这假定各方按投票数排序。

function* coalitionize(data, maxParties) {
  if (maxParties < 1)  return;
  var coalition = Array(maxParties).fill(0),
      fixedSoFar = 0;
  while (coalition[0] < data.length) {
    let actualCoalition = coalition.slice(0, fixedSoFar + 1);
    if (numSeats(data, actualCoalition) > 75) {
      yield actualCoalition.map((i) => data[i]);
      coalition[fixedSoFar]++;
    } else if (fixedSoFar < maxParties - 1) {
      // add a party to the coalition, simply the next party
      fixedSoFar++;
      coalition[fixedSoFar] = coalition[fixedSoFar - 1] + 1;
    } else {
      // cannot add more parties; quit this approach
      fixedSoFar--;
      coalition[fixedSoFar]++;
    }
    // check if we don't try anything stupid
    while (coalition[fixedSoFar] >= data.length) {
      // cannot add more parties; quit this approach
      fixedSoFar--;
      coalition[fixedSoFar]++;
    }
  }
}

function numSeats(data, coalition) {
  return coalition
    .map((i) => data[i][2] * (150 / 100))
    .reduce((a, v) => a + v, 0);
}

这会使用Generatoryield联盟,这些联盟会在找到后立即找到。它稍微简化了其余的代码,因为联盟不需要存储在数组中。 Browser support很好,但在IE中没有支持。当然,如果需要,您可以将其更改为使用数组。

请注意,联盟中的参与方数量是此处的参数,因此您可以根据需要对其进行调整。全球的想法是,这个功能只考虑最小的联盟。也就是说,当VVD,PVDA和PVV可以组成联盟时,那些人加上CDA也是一个联盟,但我们不考虑这些。现在,我们从一个政党联盟开始。如果它运作良好,请报告联盟并继续前进到下一个聚会。如果没有,请尽可能为联盟增加一方。如果我们不能,请删除最后添加的一方并继续尝试下一方。

我们可以跟踪我们在数组中尝试的各方,在coalition函数中这是coalitionize。阵列的长度是可以参加联盟的最大党派数量。每个值都是派对数组中的索引,表示我们正在为该时段尝试哪一方。为了跟踪阵列中实际有多少方,我们有变量fixedSoFar。从技术上讲,你可以不用这个变量做一堆数组操作(pushpop),但这对我来说似乎更清晰,更快。

我在小提琴中实现了稍微完整的demo。它报告在页面上以文本形式发现的联盟,并显示联盟拥有多少(部分)席位。

编辑。如果输入数据按投票数排序,那么算法不需要考虑我最初想的那么多潜在的联盟。我已经在updated demo中实现了这一点。

唯一的变化是外部else循环中的最终while子句变为以下内容。

do {
  fixedSoFar--;
  if (fixedSoFar < 0)  return;
    coalition[fixedSoFar]++;
} while ((fixedSoFar === maxParties - 2 &&
    coalition[fixedSoFar] === coalition[fixedSoFar + 1]) ||
    coalition[fixedSoFar] + 1 === coalition[fixedSoFar + 1]);

这里的关键见解是,当一个联盟没有足够的席位才能生效时,我们可以排除所有保证拥有更少席位的联盟,因为要考虑的各方只能在双方当前考虑之后才会出现。 / p>

这使得所考虑的潜在联盟数量产生巨大差异。

答案 1 :(得分:3)

如果计数小于最大项目数和座位数,您可以使用搜索和测试。

&#13;
&#13;
<pre id="out"></pre>
&#13;
        private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
    {
        if ((e != null) && (sender != null))
        {
            // on ne récupère que les évènement concernant l'axe Y. L'axe X se gère tout seul car il est unique
            if (e.Axis.AxisName.ToString() == "Y")
            {
                // AxisY.ScaleView.ViewMinimum is the minimum Y axis value displayed. It contains the offset to apply to label, grid and interval on Y axis
                e.ChartArea.AxisY.IntervalOffset = (e.ChartArea.AxisY.Interval - e.ChartArea.AxisY.ScaleView.ViewMinimum) % e.ChartArea.AxisY.Interval;

                // To update Y axis label, major grid and interval. 
                e.ChartArea.AxisY.Interval = (e.ChartArea.AxisY.ScaleView.ViewMaximum - e.ChartArea.AxisY.ScaleView.ViewMinimum) / 11;

            }
        }
    }
&#13;
&#13;
&#13;