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

时间:2021-08-15 07:36:19

I have an array of elements like so:

我有一系列元素如下:

messages[i], where messages[i] may only exist for certain values of i. For instance messages[0] and messages[2] may exist but not messages[1].

messages [i],其中messages [i]可能仅存在于i的某些值。例如,消息[0]和消息[2]可能存在但不存在消息[1]。

Now I would like to group together elements with continuous indices, for example if the indices for which messages existed were:

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

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

I would like to group them like so:

我想像他们这样分组:

2, 3, 4, 5

2,3,4,5

8, 9

12, 13, 14, 15, 16, 17

12,13,14,15,16,17

20

What would be an effective way to do so using Javascript?

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

EDIT:

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
   }
}

4 个解决方案

#1


3  

You can use a counter variable which has to be incremented and the difference between the index and the consecutive elements are the same, group them in a temporary array. If the difference is varies for two consecutive array elements, the temporary element has to be moved to the result and the temporary array has to be assigned a new array object.

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

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

#2


4  

Given :

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

(or the almost equivalent array where the undefined elements don't exist at all, but where the defined elements have the same indices as above) this reduce call will return a two-dimensional array where each top level element is the contents of the original array, grouped by contiguously defined entries:

(或几乎等效的数组,其中未定义的元素根本不存在,但定义的元素具有与上面相同的索引)此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

i.e. [[ 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]]

NB: this could also be written using a .forEach call, but I like .reduce because it requires no temporary variables - all state is encapsulated in the function parameters.

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

#3


0  

I would iterate through the list, and if you find an element at messages[i], add i to a list of mins. Then, once you don't find an element at messages[j], and j to a list of maxes.

我会迭代列表,如果你在messages [i]找到一个元素,将i添加到一个mins列表中。然后,一旦在消息[j]中找不到元素,并且j在maxes列表中找不到。

Then you will have two lists (or one, if you use a container, as I probably would) that contains the start and stop indexes of the groups.

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

#4


0  

Another approach would be something like this. I'm using a library called lodash for my array manipulation.

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

Basically I'm sorting the array in ascending order. And then for every increment, I'm storing the current element to a temporary array and comparing the last value of that array to the current element if they are in sequence if not I push the values of the temporary array to my result array and so on. If my loop reaches the end I just push the values of my temporary array to my results array.

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

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

#1


3  

You can use a counter variable which has to be incremented and the difference between the index and the consecutive elements are the same, group them in a temporary array. If the difference is varies for two consecutive array elements, the temporary element has to be moved to the result and the temporary array has to be assigned a new array object.

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

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

#2


4  

Given :

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

(or the almost equivalent array where the undefined elements don't exist at all, but where the defined elements have the same indices as above) this reduce call will return a two-dimensional array where each top level element is the contents of the original array, grouped by contiguously defined entries:

(或几乎等效的数组,其中未定义的元素根本不存在,但定义的元素具有与上面相同的索引)此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

i.e. [[ 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]]

NB: this could also be written using a .forEach call, but I like .reduce because it requires no temporary variables - all state is encapsulated in the function parameters.

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

#3


0  

I would iterate through the list, and if you find an element at messages[i], add i to a list of mins. Then, once you don't find an element at messages[j], and j to a list of maxes.

我会迭代列表,如果你在messages [i]找到一个元素,将i添加到一个mins列表中。然后,一旦在消息[j]中找不到元素,并且j在maxes列表中找不到。

Then you will have two lists (or one, if you use a container, as I probably would) that contains the start and stop indexes of the groups.

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

#4


0  

Another approach would be something like this. I'm using a library called lodash for my array manipulation.

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

Basically I'm sorting the array in ascending order. And then for every increment, I'm storing the current element to a temporary array and comparing the last value of that array to the current element if they are in sequence if not I push the values of the temporary array to my result array and so on. If my loop reaches the end I just push the values of my temporary array to my results array.

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

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