2013-06-18 3 views
3

Я пытаюсь получить серию подмножеств из массива в 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; 
}) 

Критерии для разделения исходного массива является то, что последовательные равные числа должны сформировать новый массив, но если число появляется позже в исходном массиве, что последовательное равный номер должен содержать новый массив.

Есть ли способ сделать это, используя знак подчеркивания, или это должно быть сделано с помощью петель?

Благодаря

+2

Каковы ваши правила для разделения массива? группы из трех в том порядке, в котором они изначально появлялись? Что-то другое? – Xotic750

+0

Может ли jquery быть частью решения? –

+1

jquery часто является частью проблемы: P – Xotic750

ответ

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

UPDATE: Подобно тому, как чистая процентная вещь, я принял все ответы, которые были в настоящее время на странице Созданное a jsperf для них.

+1

+1 для jsperf :) – Matyas

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

Зачем вам нужно 'if (original.length> 0) {'? – jantimon

+0

Без этого, если оригинал пуст, тогда результат будет '[null]'. Если использовать проверку длины, результат будет '[]', если оригинал был пуст. – MrCode

+0

Как насчет чего-то подобного (может никогда не произойти в ситуации ОП, но не может быть уверен)? [undefined, undefined, undefined, null, null, null, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1] – Xotic750

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, но с меньшим количеством кода.

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

Как видно из таблицы jsperf analysis, изготовленной Xotic750, это изделие имеет наименее эффективное решение. Я просто перечислил его как альтернативу, может быть, самый короткий путь.

+0

Кажется, что не дает тот же результат, что и запрошенный OP: '[" 1,1,1, "," 2,2,2, "," 0,0,0, " , "1,1,1,"] ' – Xotic750

+0

Да, я понял, что возвращаю строки, поэтому я обновил ответ. – Matyas

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

Fiddle: http://jsfiddle.net/2AChG/

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.

+0

Где декларация 'v'? – Xotic750

+0

@ Xotic750 Упс, пропустил это, когда «функционально» скрипт обновился. Спасибо –

+0

Не так потрепанный для кого-то, кто хотел сделать jquery-решение;) – Xotic750