通过评估元素的数组子集

时间:2013-06-18 08:13:14

标签: javascript arrays underscore.js

我试图使用下划线从javascript中的数组中获取一系列子集。这就是我想要实现的目标:

Original array: [1,1,1,2,2,2,0,0,0,1,1,1]
Expected result: [1,1,1] [2,2,2] [0,0,0] [1,1,1]

当我使用下划线的过滤方法时,我得到三个数组:[1,1,1,1,1,1] [2,2,2] [0,0,0];我希望最后一个1的数组不会混合。

我尝试了什么:

_.filter(array, function(e){
     return e === 1;
})

分割原始数组的标准是连续的相等数字必须形成一个新数组,但如果数字在原始数组中稍后出现,则该连续相等数字必须形成 new 数组。

有没有办法使用下划线来完成此操作,还是应该使用循环来完成?

由于

6 个答案:

答案 0 :(得分:1)

一个简单的旧Javascript解决方案:

Fiddle

var original = [1,1,1,2,2,2,0,0,0,1,1,1];

var newArr = [], currentValue = null, currentArr;

if(original.length > 0){
    for(var i=0; i<original.length; i++){
        if(currentValue == null){
            currentValue = original[i];
            currentArr = [currentValue];
        } else {
            if(currentValue == original[i]){
                currentArr.push(currentValue);
            } else {
                newArr.push(currentArr);
                currentArr = [original[i]];
            }
        }
        currentValue = original[i];
    }
    newArr.push(currentArr);
}

输出:

[[1,1,1],[2,2,2],[0,0,0],[1,1,1]] 

答案 1 :(得分:1)

不确定underscrore.js中是否有特定内容可以执行此操作,但我确信它可以使用下划线语法完成。但是,您可以在POJS中执行类似的操作。

的Javascript

var testArray = [NaN, NaN, NaN, undefined, undefined, undefined, null, null, null, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1];

function is(x, y) {
    if (x === y) {
        if (x === 0) {
            return 1 / x === 1 / y;
        }

        return true;
    }

    var x1 = x,
        y1 = y;

    return x !== x1 && y !== y1;
}

function arraySplitToGroups(array) {
    var length = array.length,
        i = 0,
        newArray = [],
        subArray = [],
        current,
        last;

    while (i < length) {
        current = array[i];

        if (!is(last, current)) {
            if (subArray.length) {
                newArray.push(subArray);
            }

            subArray = [];
        }

        subArray.push(current);
        last = current;
        i += 1;
    }

    if (subArray.length) {
        newArray.push(subArray);
    }

    return newArray;
}

console.log(arraySplitToGroups(testArray));

输出

[ [NaN, NaN, NaN], [undefined, undefined, undefined], [null, null, null], [1, 1, 1], [2, 2, 2], [0, 0, 0], [1, 1, 1] ] 

jsfiddle

更新:就像纯粹的兴趣一样,我把当前页面上的所有答案都创建为jsperf

答案 2 :(得分:1)

我认为我有一些非常直接和简短的事情:

function groupValues(arr) {
    var o=[];
    var temp=0;
    for (var i=0;i<arr.length;i++){
        if (i<=0 || arr[i]!==arr[i-1]) {
            if (i>0) {
                ++temp;
            }
            o[temp]=[];
        }
        o[temp].push(arr[i]);
    }
    return o;
}

您可以查看此工作FIDDLE

答案 3 :(得分:0)

写一个这样的简单函数:

function splitArray(original) {
    var newArr = [], currentValue, currentArr;

    for (var i = 0; i < original.length; i++) {
       if (i === 0 || currentValue !== original[i]) {
         currentArr = [];
         newArr.push(currentArr);
       }
       currentArr.push(currentValue = original[i]);
    }

    return newArr;
}

查看工作 jsFiddle

它基于MrCode的示例,但代码较少。

答案 4 :(得分:0)

能帮你完成工作的oneliner将是:

var input = [1,1,1,2,2,2,0,0,0,1,1,1]; 
var output = (input.join(',')+',').match(/(\d*,)\1+/g).map(function(str){return str.replace(/,$/,'').split(',').map(Number);})

基本上它的作用:

  (input.join(',') + ',') // concatenate all numbers with a ',', and add a trailing comma to help the matching
     .match(/(\d*,)\1+/g) // match groups of numbers of the same type with comma ( "1,1,2,"  > ["1,1", "2,"] ). The * is to support null/undefined values in the original array
     .map(                // replace every match (only works in modern browsers, but you can replace it with _.map )
           function() {
              return str.replace(/,$/, '')  // remove trailing ', '
                        .split(',')         // and split the string by , "1,1,1" > [1,1,1]
                        .map(Number)        // map everything back to Number (converts undefined / null values to 0 as a sideeffect, but keeps them as a group
           }
      );

如果您不想依赖map provided by only modern browsers的可用性,可以使用下划线地图:

var input = [1,1,1,2,2,2,0,0,0,1,1,1]; 
var output = _.map((input.join(',')+',').match(/(\d*,)\1+/g), function(str){ return _.map(str.replace(/,$/,'').split(','), Number);});

<强> Bware

Xotic750 制作的jsperf analysis中可以看到,这是性能最差的解决方案。我只是将它列为替代方案,也许是最短的方式。

答案 5 :(得分:0)

var original = [1,1,1,1,1,2,2,2,0,0,0,1,1,1,3,3];
var result = [];
var temp = [];
_.each(original,function(num,index){
     temp.push(num);
     if(original[index+1] != 'undefined' && num != original[index+1])
    {
        result.push(temp);
        temp = [];
   }
});
console.log(result);

小提琴:http://jsfiddle.net/2AChG/