从阵列中获取类似/最接近的数字

时间:2017-11-17 13:24:37

标签: javascript arrays grouping

我试图找到找到相似数字的有效方法(数字之间的差异是"几乎不变" - 接近某个常数)。

例如有数组:

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];

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

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

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等值,则会将其视为接近值...

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

答案 2 :(得分:0)

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

&#13;
&#13;
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);
&#13;
&#13;
&#13;

以上日志

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