2015-10-19 4 views
0

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

data =[{"name":"A","Date":"10/19/2015","OnTime":"0.1","Purpose":"x","OffTime":"0"}, 
     {"name":"A","Date":"10/19/2015","OnTime":"0.3","Purpose":"x","OffTime":"0"}, 
     {"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"}, 
     {"name":"C","Date":"10/19/2015","OnTime":"0.02","Purpose":"z","OffTime":"0"}, 
     {"name":"C","Date":"10/19/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"} 
     {"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}] 

Я пытаюсь группе и добавить значение OnTime для имени и дате. Например, общая стоимость Ontime для А на дату 10/19/2015 Ожидаемое O/P:

dataout = [{"name":"A","Date":"10/19/2015","OnTime":"0.4"}, 
      {"name":"A","Date":"10/20/2015","OnTime":"0.01"}, 
      {"name":"B","Date":"10/19/2015","OnTime":"0.01"}, 
      {"name":"C","Date":"10/19/2015","OnTime":"0.03"}] 

Я попытался с помощью поиска решения, но нашли решение для одного ключа того, но не для нескольких ключей. Я также попытался использовать символ подчеркивания js, но не смог получить ожидаемый результат. Пожалуйста, помогите, спасибо.

+1

Если эти данные извлекаются с сервера, скажем, используя SQL, тогда было бы намного проще выполнять группировку. Javascript на самом деле не предназначен для такого рода вещей. Это можно сделать, но это правильный фокус. – NickJ

+0

Спасибо за помощь, но, к сожалению, я застрял в javascript здесь. Я пытаюсь использовать другие опции, надеялся, что это можно сделать в javascript. – hitech0101

+0

@ hitech0101, см. Решение ниже. :-D –

ответ

2

Хорошо, у меня есть что-то, что сработает для вас.

См Fiddle здесь:

http://jsfiddle.net/chrislewispac/nw0bberb/1

//make new sorted array for future map loop which goes in order 
//using underscore.js you can chain methods. The sortBy method 
//allows chaining and by multiple attributes. First sort by name 
//then sort by date and return the value to new array 'sorted' 

var sorted = _.chain(data) 
    .sortBy(function(d) {return d.name}) 
    .sortBy(function(d) { return d.Date }) 
    .value() 

//declare vars for loop 
var prevObj = {}; 
var indexToChange = 0; 
var reformattedArray = []; 

//map loop over newly sorted array. I use map here which creates a new 
//array with the results of calling a provided function on every 
//element in this array. 

var reformattedArray = sorted.map(function (obj, index) { 

    //if the previous objects date is the same as the current objects 
    //date then take index of array which contains previous object 
    //which had same name and date properties and combine the OnTime 
    //values after converting them to float values using parseFloat() 

    if (prevObj.Date == obj.Date && prevObj.name == obj.name) { 
     reformattedArray[indexToChange].OnTime = parseFloat(prevObj.OnTime) + parseFloat(obj.OnTime); 
    } 

    //if they don't match then add current object to the end of 
    //the new array 

    else { 
     reformattedArray.push(obj); 
    } 

    //at the end of the loop assign the current object to value prevObj 
    //to be used in the next iteration 
    prevObj = obj; 

    //get current length of array (which is being built in our loop) 
    //and subtract one to get index of previous object 
    indexToChange = reformattedArray.length - 1; 

    //return the newly reformatted array 

    return reformattedArray; 

}); 

console.log(reformattedArray[0]); 

Выход:

[ 
    {"name":"A","Date":"10/19/2015","OnTime":0.4,"Purpose":"x","OffTime":"0"}, 
{"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"}, 
{"name":"C","Date":"10/19/2015","OnTime":0.03,"Purpose":"z","OffTime":"0"}, 
{"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"} 
] 

Refs:

Underscore: sortBy() based on multiple attributes

http://underscorejs.org/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat

+0

«если он работает» в сочетании с объяснением кода, что делает этот код? -1 –

+0

@StephanBijzitter ты шутишь? Прокомментировано, и есть скрипка, показывающая, что она работает –

+0

Нет, я не шучу. –

-2

Что-то вроде этого, может быть:

function GroupBy(array){ 
    var fields = Array.prototype.slice.call(arguments, 1); 
    var field = fields.shift(); 

    if(field){ 

    var groupedArray = []; 
    for(var i in array){ 
     var index = array[i][field]; 
     groupedArray[index] = groupedArray[index] || []; 
     groupedArray[index].push(array[i]); 
    } 

    for(var i in groupedArray) 
     groupedArray[i] = GroupBy.bind(null, groupedArray[i]).apply(null, fields); 

    return groupedArray; 
    } 

    return array; 
} 

не проверял, поэтому не ожидаем, что он работает. Но это должно быть хорошим началом.

Вот как вы его используете.

var array = [...]; //your array 
var groupedArray = GroupBy(array, "name", "Date"); 

//Then to get records by a specific fields just: 
var A_10192015 = groupedArray["A"]["10/19/2015"]; 
+0

Попробуем это из-за спасибо. – hitech0101

+0

Не тестировалось, «не ожидайте, что это сработает», без объяснения кода, что делает этот код? -1 –

+0

Я пробовал это и не мог заставить его работать: - \ –

0

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

  1. Группа по желаемым свойствам, например «Дата» & «» Имя»
  2. Результаты, приведенные в шаге 1 возвращает массив, где каждый элемент является массивом, по крайней мере, 1 пункт => отображающего этого результата и уменьшить значение подытожить.

Doing Шаг 1 с GroupBy вместо своего рода избежать разрыва последовательности внутри кода, и позволяет назвать уменьшить.

var data = [{"name":"A","Date":"10/19/2015","OnTime":"0.1","Purpose":"x","OffTime":"0"}, 
 
    {"name":"A","Date":"10/19/2015","OnTime":"0.3","Purpose":"x","OffTime":"0"}, 
 
    {"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"}, 
 
    {"name":"C","Date":"10/19/2015","OnTime":"0.02","Purpose":"z","OffTime":"0"}, 
 
    {"name":"C","Date":"10/19/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}, 
 
    {"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}]; 
 
console.log(_(data).chain() 
 
    .groupBy(function(itm){return itm.Date + itm.name;}) // group by date & name 
 
    .map(function(itm,key){ // for every grouped item 
 
    // we sum up the values OnTime 
 
    var sum=_(itm).chain() 
 
       .pluck("OnTime") 
 
       .reduce(function(memo, value){ 
 
        return memo =memo+ Number(value); 
 
       },0.0) 
 
       .value(); 
 
    return _.object(["name","Date", "OnTime"],[itm[0].name,itm[0].Date,sum])}) 
 
    .value() 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

достаточно элегантный? Я ч ope so!

Смежные вопросы