根据对象内数字的接近程度减少数组

Reduce an array based on closeness of numbers within objects

我有一个如下所示的数组:

[  
  { "begin": 870, "end": 889, "spanType": ["plan", "gt-plan"] },
  { "begin": 890, "end": 925, "spanType": ["plan", "gt-plan"] },
  { "begin": 926, "end": 938, "spanType": ["plan", "gt-plan"] },
  { "begin": 939, "end": 958, "spanType": ["plan", "gt-plan"] },
  { "begin": 7732, "end": 7790, "spanType": ["plan", "gt-plan"] },
  { "begin": 7791, "end": 7879, "spanType": ["plan", "gt-plan"] }
]

我需要遍历它并创建一个如下所示的数组:

[  
  { "begin": 870, "end": 958, "spanType": ["plan", "gt-plan"] },
  { "begin": 7732, "end": 7879, "spanType": ["plan", "gt-plan"] }
]

基本上,如果一个 span.end 在下一个 span.begin 的 3 以内,将两个跨度合并在一起

这是我现在拥有的(不工作)see fiddle:

spans.forEach(function(d,i) {
    if (i+1 <= spans.length - 1) {
    if (spans[i+1].begin <= d.end + 3) {
    d.end = spans[i+1].end;
     newSpans.push(d);
  }
    else {
        newSpans.push(spans[i]);
    }
  }
});

see fiddle

起初我会对跨度进行排序,这样我们就不需要一遍又一遍地检查所有元素:

spans.sort((a,b) => a.begin - b.begin);

现在我们可以轻松地遍历并合并:

const result = [];
result.push(spans.reduce((prev,curr) => {
 if(prev.end < curr.begin - 1){
  result.push(prev);
  return Object.assign({},curr);
 }
 prev.end = Math.max(prev.end, curr.end);
 return prev;
}));

Try it

对于已排序的数据,您可以检查最后插入的元素与实际元素,如果增量小于所需的数字,则调整 end 值。

这个提议改变了原来的数组。如果不需要,您需要在推送时获取对象的副本。

var array = [{ begin: 870, end: 889, spanType: ["plan", "gt-plan"] }, { begin: 890, end: 925, spanType: ["plan", "gt-plan"] }, { begin: 926, end: 938, spanType: ["plan", "gt-plan"] }, { begin: 939, end: 958, spanType: ["plan", "gt-plan"] }, { begin: 7732, end: 7790, spanType: ["plan", "gt-plan"] }, { begin: 7791, end: 7879, spanType: ["plan", "gt-plan"] }],
    result = array.reduce(function (r, o, i) {
        if (!i || o.begin - r[r.length - 1].end >= 3) {
            r.push(o);
        } else {
            r[r.length - 1].end = o.end;
        }
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

const data = [  
  { "begin": 870, "end": 889, "spanType": ["plan", "gt-plan"] },
  { "begin": 890, "end": 925, "spanType": ["plan", "gt-plan"] },
  { "begin": 926, "end": 938, "spanType": ["plan", "gt-plan"] },
  { "begin": 939, "end": 958, "spanType": ["plan", "gt-plan"] },
  { "begin": 7732, "end": 7790, "spanType": ["plan", "gt-plan"] },
  { "begin": 7791, "end": 7879, "spanType": ["plan", "gt-plan"] }
];

// your range, representing how close an end has to be to a begin to merge
const RANGE = 3;

// iterate through the data still available
for (let i = 0; i < data.length - 1; i++) {
    // check if we should merge the current data object with the next one
    // based on the defined range
    if (data[i].end >= data[i+1].begin - RANGE) {
        // we'll merge the current object into the next one. 
        // first, we'll set the begin value of the next object to
        // the one that's being merged into it
        data[i+1].begin = data[i].begin;

        // now we push the current object's spanType entries into the next object
        Array.prototype.push.apply(data[i+1].spanType, data[i]);

        // finally we remove the current object from the list as it has been
        // fully merged
        data.splice(i, 1);

        // we removed an element, so we'll go one back in the list
        i--;
    }
}
console.log(data);