2015-05-27 2 views
3

Я следующие два JavaScript массивы:Преобразование массива JavaScript объектов

var grades = [ { name: "A", color: "#00FF00" }, 
       { name: "B", color: "#88CC00" }, 
       { name: "C", color: "#AAAA00" }, 
       { name: "D", color: "#CC8800" }, 
       { name: "F", color: "#FF0000" }]; 

var studentGrades = [ { Student: "James", Class: "Math", Grade: "A" }, 
         { Student: "Lily", Class: "Math", Grade: "B" }, 
         { Student: "Bob", Class: "Math", Grade: "C" }, 
         { Student: "Tom", Class: "Math", Grade: "C" }, 
         { Student: "James", Class: "Science", Grade: "A" }, 
         { Student: "Lily", Class: "Science", Grade: "B" }, 
         { Student: "Bob", Class: "Science", Grade: "B" }, 
         { Student: "Tom", Class: "Science", Grade: "B" }, 
         { Student: "James", Class: "Chemistry", Grade: "F" }, 
         { Student: "Lily", Class: "Chemistry", Grade: "A" }, 
         { Student: "Bob", Class: "Chemistry", Grade: "B" }, 
         { Student: "Tom", Class: "Chemistry", Grade: "A" } ]; 

И я пытаюсь создать следующие два массива из него:

grades = [ { name: "A", color: "#00FF00", data: [1, 1, 2] }, 
        { name: "B", color: "#88CC00", data: [1, 3, 1] }, 
        { name: "C", color: "#AAAA00", data: [2, 0, 0] }, 
        { name: "D", color: "#CC8800", data: [0, 0, 0] }, 
        { name: "F", color: "#FF0000", data: [0, 0, 1] } ]; 

var classes = [ "Math", "Science", "Chemistry" ]; 

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

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

<!DOCTYPE html> 
<html> 
    <head> 
    <base href="http://demos.telerik.com/kendo-ui/bar-charts/local-data-binding"> 
    <style>html { font-size: 12px; font-family: Arial, Helvetica, sans-serif; }</style> 
    <title></title> 
    <link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.429/styles/kendo.common-bootstrap.min.css" /> 
    <link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.429/styles/kendo.bootstrap.min.css" /> 
    <link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.429/styles/kendo.dataviz.min.css" /> 
    <link rel="stylesheet" href="http://cdn.kendostatic.com/2015.1.429/styles/kendo.dataviz.bootstrap.min.css" /> 

    <script src="http://cdn.kendostatic.com/2015.1.429/js/jquery.min.js"></script> 
    <script src="http://cdn.kendostatic.com/2015.1.429/js/kendo.all.min.js"></script> 
    </head> 
    <body> 
    <div id="example"> 
     <div class="demo-section k-content"> 
     <div id="chart"></div> 
     </div> 
     <script> 

     // Start of code that is specific to the stackoverflow question 

     var grades = [ { name: "A", color: "#00FF00" }, 
         { name: "B", color: "#88CC00" }, 
         { name: "C", color: "#AAAA00" }, 
         { name: "D", color: "#CC8800" }, 
         { name: "F", color: "#FF0000" }]; 

     var studentGrades = [ { Student: "James", Class: "Math", Grade: "A" }, 
           { Student: "Lily", Class: "Math", Grade: "B" }, 
           { Student: "Bob", Class: "Math", Grade: "C" }, 
           { Student: "Tom", Class: "Math", Grade: "C" }, 
           { Student: "James", Class: "Science", Grade: "A" }, 
           { Student: "Lily", Class: "Science", Grade: "B" }, 
           { Student: "Bob", Class: "Science", Grade: "B" }, 
           { Student: "Tom", Class: "Science", Grade: "B" }, 
           { Student: "James", Class: "Chemistry", Grade: "F" }, 
           { Student: "Lily", Class: "Chemistry", Grade: "A" }, 
           { Student: "Bob", Class: "Chemistry", Grade: "B" }, 
           { Student: "Tom", Class: "Chemistry", Grade: "A" } ]; 

     var classes = []; 

     // Returns an array that maintains the grade counts for each class based on the grades array. 
     var getGradeCounts = function (studentData, gradeCounts) { 
      if (gradeCounts == null) { 
       gradeCounts = []; 
      } 
      for (var i = 0; i < grades.length; i++) { 
       if (gradeCounts[i] == undefined) { 
        gradeCounts[i] = 0; 
       } 
       if (grades[i].name === studentData.Grade) { 
        gradeCounts[i]++; 
       } 
      } 
      return gradeCounts; 
     } 

     // Iterates over each student grade and maintains an object of the grade counts by class, and an unique array of classes used for the chart category. 
     var classGradeCounts = {}; 
     for (var student in studentGrades) { 
      var studentClass = studentGrades[student].Class; 
      if (classGradeCounts[studentClass] == undefined) { 
       classes.push(studentClass); 
      } 
      classGradeCounts[studentClass] = getGradeCounts(studentGrades[student], classGradeCounts[studentClass]); 
     } 

     // Now that we have the grade counts for each class, build up the chart series 
     for (var i = 0; i < grades.length; i++) { 
      grades[i].data = []; 
      for (var classGradeCount in classGradeCounts) { 
       grades[i].data.push(classGradeCounts[classGradeCount][i]); 
      } 
     } 

     // End of stackoverflow code, the rest of this is code is used to generate a Kendo chart. 

     var chartSettings = { 
      seriesDefaults: { type: "column", stack: true }, 
      series: grades, 
      categoryAxis: { categories: classes }, 
     }; 

     function createChart() { 
      $("#chart").kendoChart(chartSettings); 
     } 

     $(document).ready(createChart); 
     $(document).bind("kendo:skinChange", createChart); 
     </script> 
    </div> 


    </body> 
</html> 
+6

Определение * легко * ... Looping неизбежен, один так или иначе ... –

+0

Можете ли вы объяснить, где свойство «данные» происходит от вашей серии графика? Вам придется перебирать свои массивы, никоим образом не обойти это. – bhspencer

+0

Возможный дубликат [Сортировка и объединение ключей JSON с соответствующими значениями] (http://stackoverflow.com/questions/26977121/sort-and-merge-json-keys-with-matching-values) – dave

ответ

3

Вы не можете избежать петель. Вы можете придать ему отсутствие петель с помощью таких функций, как Array.prototype.forEach и Array.prototype.map.

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

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

var grades = [ { name: "A", color: "#00FF00" }, 
 
       { name: "B", color: "#88CC00" }, 
 
       { name: "C", color: "#AAAA00" }, 
 
       { name: "D", color: "#CC8800" }, 
 
       { name: "F", color: "#FF0000" }]; 
 

 
var studentGrades = [ { Student: "James", Class: "Math", Grade: "A" }, 
 
         { Student: "Lily", Class: "Math", Grade: "B" }, 
 
         { Student: "Bob", Class: "Math", Grade: "C" }, 
 
         { Student: "Tom", Class: "Math", Grade: "C" }, 
 
         { Student: "James", Class: "Science", Grade: "A" }, 
 
         { Student: "Lily", Class: "Science", Grade: "B" }, 
 
         { Student: "Bob", Class: "Science", Grade: "B" }, 
 
         { Student: "Tom", Class: "Science", Grade: "B" }, 
 
         { Student: "James", Class: "Chemistry", Grade: "F" }, 
 
         { Student: "Lily", Class: "Chemistry", Grade: "A" }, 
 
         { Student: "Bob", Class: "Chemistry", Grade: "B" }, 
 
         { Student: "Tom", Class: "Chemistry", Grade: "A" } ]; 
 

 
var gradeMap={}, gradesByClass={}, classMap={}, classArray=[], classIndex=0; 
 

 
grades.forEach(function(grade) { 
 
    gradeMap[grade.name] = grade.color; 
 
}); 
 
    
 
studentGrades.forEach(function(studentGrade){ 
 
    if (!gradesByClass[studentGrade.Class]) { 
 
     gradesByClass[studentGrade.Class] = {}; 
 
     classMap[studentGrade.Class] = classIndex; 
 
     classIndex++; 
 
    } 
 
    if(!gradesByClass[studentGrade.Class][studentGrade.Grade]) { 
 
     gradesByClass[studentGrade.Class][studentGrade.Grade] = 0; 
 
    } 
 
    gradesByClass[studentGrade.Class][studentGrade.Grade]++; 
 
}); 
 

 
Object.keys(classMap).forEach(function(className){ 
 
    classArray[classMap[className]] = className; 
 
}); 
 

 
var finalGrades = Object.keys(gradeMap).map(function(grade){ 
 
    var obj = { 
 
     name: grade, color: gradeMap[grade], data: [] 
 
    }; 
 
    classArray.forEach(function(className, index){ 
 
     if (gradesByClass[className] && gradesByClass[className][grade]) { 
 
      obj.data[index] = gradesByClass[className][grade]; 
 
     } else { 
 
      obj.data[index] = 0; 
 
     }   
 
    }); 
 
    return obj; 
 
}); 
 

 
console.log(JSON.stringify(finalGrades)); 
 
/* 
 
[{"name":"A","color":"#00FF00","data":[1,1,2]}, 
 
{"name":"B","color":"#88CC00","data":[1,3,1]}, 
 
{"name":"C","color":"#AAAA00","data":[2,0,0]}, 
 
{"name":"D","color":"#CC8800","data":[0,0,0]}, 
 
{"name":"F","color":"#FF0000","data":[0,0,1]}] 
 
*/

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