2016-11-09 4 views
2

Довольно сложно объяснить, поэтому я попытаюсь быть явным.Javascript: добавление 0 значений в массивы разных размеров

У меня есть объект, данные, который представляет собой массив объектов, который включает в себя массив объектов и строку:

var groups = [ 
    { 
     bars: [ 
      {label: 'a', value: 28}, 
      {label: 'c', value: 16} 
     ], 
     string: 'one' 
    }, 
    { 
     bars: [ 
      {label: 'a', value: 3}, 
      {label: 'b', value: 17}, 
      {label: 'c', value: 24} 
     ], 
     string: 'two' 
    }, 
    { 
     bars: [ 
      {label: 'a', value: 12}, 
      {label: 'd', value: 7}, 
      {label: 'e', value: 36} 
     ], 
     string: 'three' 
    }, 
    { 
     bars: [ 
      {label: 'c', value: 32}, 
      {label: 'e', value: 2} 
     ], 
     string: 'four' 
    } 
] 

мне нужно все «бары» объекты, чтобы быть того же размера и иметь 0 значение, если объект для указанной метки не существует. Как вы можете видеть, ключ метки, связанный с «барами», является конечным списком. Моя главная проблема здесь в том, что размер объекта «groups», а также размер объекта «bars» является динамическим. С подчеркиванием, я использовал:

var labelNames = _.uniq(_.flatten 
    (_.map(data.groups,function(groups) { 
    return _.pluck(groups.bars, 'label'); 
}))); 

извлечь список известных лейблов дает мне

['a', 'b', 'c', 'd', 'e'] 

теперь я хочу, чтобы отобразить этот массив баров объект дает мне этот выход:

var groups = [ 
    { 
     bars: [ 
      {label: 'a', value: 28}, 
      {label: 'b', value: 0}, 
      {label: 'c', value: 16}, 
      {label: 'd', value: 0}, 
      {label: 'e', value: 0} 
     ], 
     string: 'one' 
    }, 
    { 
     bars: [ 
      {label: 'a', value: 3}, 
      {label: 'b', value: 17}, 
      {label: 'c', value: 24}, 
      {label: 'd', value: 0}, 
      {label: 'e', value: 0} 
     ], 
     string: 'two' 
    }, 
    { 
     bars: [ 
      {label: 'a', value: 12}, 
      {label: 'b', value: 0}, 
      {label: 'c', value: 0}, 
      {label: 'd', value: 7}, 
      {label: 'e', value: 36} 
     ], 
     string: 'three' 
    }, 
    { 
     bars: [ 
      {label: 'a', value: 0}, 
      {label: 'b', value: 0}, 
      {label: 'c', value: 32}, 
      {label: 'd', value: 0}, 
      {label: 'e', value: 2} 
     ], 
     string: 'four' 
    } 
] 

Если это полезно, у меня должны быть даже бары, потому что я создал серию высоких диаграмм с этими объектами like this example. Надеюсь, это имеет смысл. Любая помощь будет оценена по достоинству. Я сошел с ума, пытаясь понять это.

+2

Прокрутите каждый элемент 'групп' с помощью' _.each'. Используйте '_.pluck', чтобы получить все метки' bars' и '_.difference' между этим и известными ярлыками, чтобы получить недостающие. Затем добавьте элементы с этими метками и 'значение: 0'. – Barmar

+0

Спасибо! Это доставило мне большую часть пути, поэтому я отправляю его как ответ – bspckl

ответ

3

Вот что я пошел с тем, кто наткнуться на это.

_.each(data.groups, function(group) { 
    var currentValues = _.pluck(group.bars, 'label'); 
    var zeroValues = _.difference(labelNames, currentValues); 
    _.each(zeroValues, function(newLabel) { 
     group.bars.push({label: newLabel, value: 0}); 
    }); 
}); 
+1

Очень приятно, на самом деле демонстрирует силу underscore.js. – Barmar

1

Это должно сделать трюк:

// First, iterate over each group 
for (var i = 0; i < groups.length; i++) { 

    var bars = groups[i].bars; 

    // Second, iterate over each of the previously collected labels, e.g. var labels = ['a', 'b', 'c', 'd', 'e'] 
    for (var j = 0; j < labels.length; j++) { 

     // Assume label does not exist, until proven otherwise 
     var labelDoesNotExist = true; 

     // Third, iterate over the bars' existing labels 
     for (var k = 0; k < bars.length; k++) { 

      var label = bars[k].label; 

      // Check if the label matches the current iteration of pre-collected labels 
      if (label == labels[j]) { 
       labelDoesNotExist = false; 
      } 
     } 

     // If no existing label matches any of the pre-collected labels, then create a new label with value of 0 
     if (labelDoesNotExist) { 
      bars.push({ 
       'label': labels[j], 
       'value': '0' 
      }); 
     } 
    } 
} 
1

Функциональная и EcmaScript6 альтернатива:

Во-первых, получить метки: [ 'а', «Ь 'с', ...]

let labels = groups 
    .reduce((res, item) => 
    [...res, ...item.bars.map(b => b.label)], 
    []) 
    .filter((value, index, self) => 
    self.indexOf(value) === index 
) 
    .sort() 

Сохранение дня с уменьшением и конкат!

И второй шаг, сделать работу без библиотек поставщика:

let newgroups = groups.map(item => 
    Object.assign({}, item, {bars : [ 
    ...item.bars, 
    ...labels.filter(l => 
     !item.bars.some(b => b.label == l) 
    ) 
     .map(l => ({label:l, value:0})) 
    ].sort((a, b) => a.label < b.label ? -1:1)}) 
); 

Окончательный sort является opcional, но бары itens может быть лучше с этим.

Работы на хромовых и реальных двигателях без перелива. ES6 is life

+0

Более читаемая альтернатива https://gist.github.com/AbraaoAlves/e1ed0cc21eca5750fa80610e3674bd05 –