使用Javascript将连续元素分组在一起

时间:2014-03-25 06:40:05

标签: javascript arrays

我有一系列元素如下:

messages[i],其中messages[i]可能只存在i的某些值。例如,messages[0]messages[2]可能存在,但不存在messages[1]

现在我想将具有连续索引的元素组合在一起,例如,如果存在消息的索引是:

2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20

我想将它们分组:

2, 3, 4, 5

8, 9

12, 13, 14, 15, 16, 17

20

使用Javascript这样做的有效方法是什么?

修改

for (i = 0; i < messages.length; i++) {
   if (messages[i].from_user_id == current_user_id) {
   // group the continuous messages together
      } else {
  //group these continuous messages together
   }
}

5 个答案:

答案 0 :(得分:4)

您可以使用必须递增的计数器变量,并且索引和连续元素之间的差异相同,将它们分组到临时数组中。如果两个连续数组元素的差异不同,则必须将临时元素移动到result,并且必须为临时数组分配新的数组对象。

var array = [2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20];

var result = [], temp = [], difference;
for (var i = 0; i < array.length; i += 1) {
    if (difference !== (array[i] - i)) {
        if (difference !== undefined) {
            result.push(temp);
            temp = [];
        }
        difference = array[i] - i;
    }
    temp.push(array[i]);
}

if (temp.length) {
    result.push(temp);
}

console.log(result);
# [ [ 2, 3, 4, 5 ], [ 8, 9 ], [ 12, 13, 14, 15, 16, 17 ], [ 20 ] ]

答案 1 :(得分:4)

鉴于:

var data = [ undefined, undefined, 2, 3, 4, 5,
             undefined,undefined, 8, 9,
             undefined, undefined, 12, 13, 14, 15, 16, 17,
             undefined, undefined, 20];

(或undefined元素根本不存在的几乎等效的数组,但定义的元素具有与上述相同的索引),此reduce调用将返回两个 - 维数组,其中每个顶级元素是原始数组的内容,按连续定义的条目分组:

var r = data.reduce(function(a, b, i, v) {
    if (b !== undefined) {              // ignore undefined entries
        if (v[i - 1] === undefined) {   // if this is the start of a new run
            a.push([]);                 // then create a new subarray
        }
        a[a.length - 1].push(b);        // append current value to subarray
    }
    return a;                           // return state for next iteration
}, []);                                 // initial top-level array

即。 [[ 2, 3, 4, 5], [8, 9], [12, 13, 14, 15, 16, 17], [20]]

注意:这也可以使用.forEach调用来编写,但我喜欢.reduce,因为它不需要临时变量 - 所有状态都封装在函数参数中。

答案 2 :(得分:0)

我将遍历列表,如果您在messages[i]找到元素,请将i添加到分钟列表中。然后,一旦您在messages[j]找不到元素,并且j找到最大值列表。

然后你将有两个列表(或者一个,如果你使用容器,我可能会这样),它包含组的开始和停止索引。

答案 3 :(得分:0)

另一种方法是这样的。我使用名为lodash的库进行数组操作。

基本上我按升序对数组进行排序。然后对于每个增量,我将当前元素存储到临时数组并将该数组的最后一个值与当前元素进行比较(如果它们是顺序的话)如果不是我将临时数组的值推送到我的结果数组等等。如果我的循环到达结尾,我只需将临时数组的值推送到结果数组。

var _ = require('lodash');
var arr = [2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20];
arr = _.sortBy(arr, function (o) {
    return o;
});
var tmp = [];
var res = [];
for (var i = 0; i < arr.length; i++) {
    if (tmp.length === 0) {
        tmp.push(arr[i]);
    }
    else {
        var lastEl = _.last(tmp);
        if ((lastEl + 1) === arr[i]) {
            tmp.push(arr[i]);
        }
        else {
            res.push(tmp);
            tmp = [];
            tmp.push(arr[i]);
        }
        if (i === (arr.length - 1)) {
            res.push(tmp);
            tmp = [];
        }
    }
}
// Outputs: [ [ 2, 3, 4, 5 ], [ 8, 9 ], [ 12, 13, 14, 15, 16, 17 ], [ 20 ] ]

答案 4 :(得分:0)

const cluster = (arr, tmp = [], result = []) => 
    (result = arr.reduce((acc, c, i) => 
        (!tmp.length || c === (arr[i-1]+1)
            ? (tmp.push(c), acc) 
            : (acc.push(tmp), tmp = [c], acc))
            , []), tmp.length ? (result.push(tmp), result) : result)

console.log(cluster([2, 3, 4, 5, 8, 9, 12, 13, 14, 15, 16, 17, 20]))