【问题标题】:Sort collections by ranking them in multiple criteria通过在多个标准中对集合进行排序来对集合进行排序
【发布时间】:2015-01-26 22:49:04
【问题描述】:

这就是我要解决的任务。

我们有一个主阵列和几个像这样的仆从阵列:

var master = [3, 2, 2, 4, 15, 8];
var minions = [
  {
    id : "Minion1",
    imitation : [2, 1, 0, 3, 11, 5],
  },
  {
    id : "Minion2",
    imitation : [1, 3, 2, 1, 12, 7],
  },
  {
    id : "Minion3",
    imitation : [4, 3, 1, 1, 11, 6],
  }
];

让我们假设奴才试图模仿大师。我们需要通过给他们打分来知道谁做得更好。

限制: - 可以有任意数量的仆从 - 我们只比较数值 - 数组中的数字数量始终保持不变


所以我想出了这个逻辑:

  1. 从master中对应的数字中减去minions数组中的每个数字,得到这个的绝对值。因为如果 Master 有第一个 3 号,Minion1 有 2 号,Minion3 有 4 号。Minion1 和 Minion3 距离 Master 一样远。

  2. 将每个 minion 的绝对值推送到数组中。

  3. 比较数组中的绝对值并对数组中的每个数字进行排序。 也许类似于 master[0]:

    • 小黄人1[0]
    • 小黄人3[0]
    • 小黄人2[0]
  4. 根据它们的位置,为数组中的每个数字分配点,相互比较。 大师[0]:

    • 小黄人1[0] +3 分
    • Minion3[0] +2 分
    • 小黄人2[0] +1 分
  5. 对 minions 数组中每个数字的点求和。比较 sums 和 console.log 是更好的模仿者


现在,我被困在第 3 步。将感谢我的代码或逻辑上的任何 cmets,谢谢 :)

这是我目前得到的:

var Master = [3, 2, 2, 4, 15, 8];
var minions = [
  {
    id : "minion1",
    mimic_result : [2, 1, 0, 3, 11, 5],
    abs_values : [],
    points : []
  },
  {
    id : "minion2",
    mimic_result : [1, 3, 2, 1, 12, 7],
    abs_values : [],
    points : []
  },
  {
    id : "minion3",
    mimic_result : [6, 0, 0, 0, 0, 1],
    abs_values : [],
    points : []
  }
];

for(i=0;i<Master.length;i++){
  for(j=0;j<minions.length;j++) {
  var result = Math.abs(Master[i]-minions[j].mimic_result[i]);
  minions[j].abs_values.push(result);
    }
}

for(k=0;k<minions.length;k++) {
  console.log(minions[k].result[0]);
  
}

console.log(minions[0].abs_values);
console.log(minions[1].abs_values);
console.log(minions[2].abs_values);

【问题讨论】:

    标签: javascript arrays


    【解决方案1】:

    使用Lo-Dash

    var minionPoints = minions.map(function (minion, i) {
        return {
            minionIndex: i,
            points: 0
        };
    });
    master.forEach(function (masterValue, masterIndex) {
        var distances = [],
            buckets = [],
            points = 0;
        // calculate distances from master on one individual property
        minions.forEach(function (minion, minionIndex) {
            distances.push({
                minionIndex: minionIndex,
                distance: Math.abs(masterValue - minion.imitation[masterIndex])
            });
        });
        // divide into buckets containing items with same distance
        // (ordered from largest distance to smallest)
        _.sortBy(distances, 'distance').forEach(function (o) {
            if (buckets[0] && (o.distance === buckets[0][0].distance)) {
                buckets[0].push(o);
            } else {
                buckets.unshift([o]);
            }
        });
        // calculate point gain for each item in the bucket
        // (if there are 2 items in the last and second-last place, they should each get 1.5 points)
        buckets.forEach(function (bucket) {
            var totalGain = points + bucket.length + ((bucket.length * (bucket.length + 1)) / 2)
                individualGain = totalGain / bucket.length;
            bucket.forEach(function (o) {
                minionPoints[o.minionIndex].points += individualGain;
            });
            points += totalGain;
        });
    });
    _.sortBy(minionPoints, 'points').reverse().forEach(function (o, i) {
        console.log((i + 1) + '. ' + minions[o.minionIndex].id + ' (' + o.points +
                ' points, imitation [' + minions[o.minionIndex].imitation.join(', ') +
                '])');
    });
    

    它会按照您的建议计算距离和点。此外,当多个随从的距离相同时,它们的总点数增益在它们之间平均分配。 Working demo.

    (出于懒惰,我自动包含了 Lo-Dash。我最终只将它用于排序,这可以像使用原生 Array.prototype.sort 一样轻松完成。)

    【讨论】:

      【解决方案2】:

      您可以将数组视为 n 维空间中的点并计算它们之间的Euclidean distance

      function dist(a, b) {
          return Math.sqrt(a.reduce(function(sum, _, i) { return sum + Math.pow(a[i] - b[i], 2) }, 0));
      }
      

      然后

      minions.sort(function(a, b) {
          return dist(master, a.imitation) - dist(master, b.imitation);
      });
      

      【讨论】:

      • 计算 something 的好方法,但与 OP 提出的指标完全无关(分别在每个维度中对“奴才”进行排名,并根据 他们的排名,而不是他们的距离)。想想一个仆从,他的模仿在所有坐标中都是正确的,除了一个坐标之外,并且在那个坐标中非常偏离。但是,它肯定是一种更简洁的方法来测量“与原始的距离”。
      • @hon2a:据我了解,OP想要找出哪个数组最接近某个点,这就是所谓的“距离”。到目前为止,他们的逻辑在我看来像是一次不成功的计算尝试,我冒昧地不遵循它。
      • 无论如何,OP 需要澄清整件事的全部内容。
      【解决方案3】:

      首先,在 : 中引发了一个异常 ts:

      for(k=0;k<minions.length;k++) {
        console.log(minions[k].result[0]);
      }
      

      应该是:

      for(k=0;k<minions.length;k++) {
        console.log(minions[k].mimic_result[0]);
      }
      

      或者据我了解,您想检查您必须执行的 abs_values 值:

      for(k=0;k<minions.length;k++) {
        console.log(" the minions["+k+"] abs_values are:\n"); 
        for(l=0;l<minions.abs_values.length;l++) {
          console.log(minions[k].abs_values[l]);
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 2020-09-16
        • 2019-04-24
        相关资源
        最近更新 更多