【问题标题】:Get similiar/closest numbers from the array从数组中获取相似/最接近的数字
【发布时间】:2017-11-17 13:24:37
【问题描述】:

我正在尝试找到找到相似数字的有效方法(其中数字之间的差异“几乎恒定” - 接近某个恒定)。

例如有这样的数组:

const arr = [23, 130, 142, 151, 163, 200];

将返回一个新数组:

const similarNumbers = [130, 142, 151, 163];

目前我尝试解决的方法是映射第一个数组并尝试找到数字之间的最小差异,然后再次映射并检查currentValue - previousValue - smallestGap < SOME_THRESHOLD的绝对值,但这并不理想,只能工作在某些特殊情况下。

理想情况下,我想要实现的是函数返回一些具有分组相似数字的数组:

const someArr = [23, 130, 142, 151, 163, 200, 232, 261];

将返回两个数组:

group1 = [130, 142, 151, 163];

和:

group2 = [200, 232, 261];

【问题讨论】:

  • 基于什么?!科学和信息学是精确的。我们需要准确的规则来解决这个问题

标签: javascript arrays grouping


【解决方案1】:

这是我刚刚编写的一个简单(并不完美)的函数。它将根据一个阈值将数字分组,该阈值定义了与组平均值的最大偏差。

const someArr = [23, 130, 142, 151, 163, 200, 232, 261];
var threshold = 50;

var relations = {};
var groups = {};


i = 0;
for (var j = 0; j < someArr.length; j++) {
  var number = someArr[j];
  if (i == 0) {
    relations[number] = i;
    groups[i] = [];
    groups[i].push(number);
  }
  else {
    var added = false;
    var n_groups = 0;
    for (var g in groups) {
      var sum = 0;
      var group = groups[g];
      if (group.length == 1 && Math.abs(number - group[0]) <= 2 * threshold) {
        relations[number] = parseInt(g, 10);
        groups[g].push(number);
        added = true;
      }
      else {
      for( var n = 0; n < group.length; n++ ){
          sum += group[n];
      }
      var avg = sum/group.length;
      if (Math.abs(number - avg) <= threshold) {
        relations[number] = parseInt(g, 10);
        groups[g].push(number);
        added = true;
      }
      }
      n_groups++;
    }
    if (!added) {
      var h = n_groups;
      relations[number] = parseInt(h, 10);
      groups[h] = [];
      groups[h].push(number);
    }
  }
  i++;
}

//console.log(relations, groups);

document.getElementById('grouped').innerHTML = JSON.stringify(groups);
<h3>Input</h3><div id="original">[23, 130, 142, 151, 163, 200, 232, 261]</div>
<h3>Output</h3><div id="grouped"></div>

【讨论】:

    【解决方案2】:

    我不确定这是你想要得到的结果。

    function(entries) {
      let groups = {};
      let finalGroups = {};
      for (var i = 0; i < entries.length; i++) {
        let b = entries[i];
        let power = 0;
        while(b > 10) {
          power++;
          b = b / 10
        }
    
        groups[power] = groups[power] || []
        groups[power].push(a[i]);
      }
    
      for (let i in groups) {
    
        for (let j = 0; j < groups[i].length; j++) {
          const c = groups[i][j]
          const max = Math.floor(c / Math.pow(10, i));
          finalGroups[i] = finalGroups[i] || {};
          finalGroups[i][max] = finalGroups[i][max] || [];
          finalGroups[i][max].push(c);
        }
      }
    
      return finalGroups;
    }
    

    这是结果。您将需要提取数组,但这不是困难的部分

    {
      "1":
        {
          "2":[23]
        },
      "2":
        {
          "1":[130,142,151,163],
          "2":[200,232,261]
        }
     }
    

    该函数将首先按 10 的幂对条目进行排序。然后将按左侧最多的数字对它们进行排序。

    因此,如果您有 10301203 之类的值,它们将被视为接近值...

    编辑:犯了一个错误。修好了

    【讨论】:

      【解决方案3】:

      如果您想找到两组彼此更相似的数字,对于最简单的集合,您可以将它们分成两半,并找出第一个/最后一个项目之间的差异,以及项目之间的差异在该项目之前/之后,如果它更接近另一组中的项目,则保持原样

      const someArr = [23, 130, 142, 151, 163, 200, 232, 261];
      
      someArr.sort((a, b) => a < b ? -1 : 1);
      
      let groupA = someArr.slice(0, Math.ceil(someArr.length / 2))
      let groupB = someArr.slice(Math.ceil(someArr.length / 2));
      
      const differenceInA = Math.abs(groupA[groupA.length - 2] - groupA[groupA.length - 1]);
      const differenceInB = Math.abs(groupB[0] - groupB[1]);
      const differenceInBoth = Math.abs(groupA[groupA.length - 1] - groupB[0])
      
      if (differenceInBoth < differenceInB) {
         groupA.push(groupB[0]);
         groupB = groupB.slice(1);
      } else if(differenceInBoth > differenceInA) {
         groupB.unshift( groupA[groupA.length - 1]);
         groupA = groupA.slice(0, groupA.length - 1);
      }
      
      console.log('Group A:', groupA);
      console.log('Group B:', groupB);

      以上日志

      Group A: [
        23,
        130,
        142,
        151,
        163
      ]
      Group B: [
        200,
        232,
        261
      ]
      

      【讨论】:

        猜你喜欢
        • 2012-01-24
        • 2012-10-30
        • 1970-01-01
        • 2019-06-30
        • 1970-01-01
        • 1970-01-01
        • 2023-03-20
        • 2022-01-16
        相关资源
        最近更新 更多