Можете вы помочь мне?

Я новичок в JavaScript. У меня есть 2 массива, x и y, и моя страница заполняет эти массивы двумя вариантами, первый со случайными числами, а второй со входами.

let numberX = [10, 22, 33];
let numberY = [34, 44, 9];

Но мне нужен такой объект:

let allData =
[{
    Rating:10,//x
    Count:20,//y
    Duration:0,//this number isn't needed
  }];

Как я могу преобразовать 2 простых массива в структуру, подобную объекту?

Мой HTML-код:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Linear Regression</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css"/>
</head>

<body>
    <form action="" method="post">
        <input type="text" name="x1"  placeholder="Type x1">
        <input type="text" name="y1" placeholder="Type y1">
        <br>
        <input type="text" name="x2"  placeholder="Type x2">
        <input type="text" name="y2" placeholder="Type y2">
        <br>
        <input type="text" name="x3"  placeholder="Type x3">
        <input type="text" name="y3"  placeholder="Type y3">
        <br>
        <input type="text" name="x4"  placeholder="Type x4">
        <input type="text" name="y4"  placeholder="Type y4">
        <br>
        <input type="text" name="x5"  placeholder="Type x5">
        <input type="text" name="y5"  placeholder="Type y5">
        <br>
        <input type="text" name="x6"  placeholder="Type x6">
        <input type="text" name="y6"  placeholder="Type y6">
        <br>
        <input type="text" name="x7"  placeholder="Type x7">
        <input type="text" name="y7"  placeholder="Type y7">
        <br>
        <input type="text" name="x8"  placeholder="Type x8">
        <input type="text" name="y8"  placeholder="Type y8">
        <br>
        <input type="text" name="x9"  placeholder="Type x9">
        <input type="text" name="y9"  placeholder="Type y9">
        <br>
        <input type="text" name="x10"  placeholder="Type x10">
        <input type="text" name="y10"  placeholder="Type y10">
        <br>
        <button type="button" onclick="generateNumbers()">Plot Numbers</button>
        <button type="button" onclick="generateRandomNumbers()">Plot Random Numbers</button>
        </br></br></br></br>
        <div id="divTable"></div>
        <div id="divSVG"></div>
        <div id="title"></div>
            <text id="equation"></text>
            <div id="graph-wrapper">

              <div id="graph-wrapper-y">
                <text>Eje Y</text>
                <select id="graph-picklist-y" class="graph-picklist">
                  <option value="Rating" selected>Average Rating</option>
                  <option value="Count">Attendee Count</option>
                </select>
              </div>

              <div id="graph-wrapper-x">
                <text>Eje X</text>
                <select id="graph-picklist-x" class="graph-picklist">
                  <option value="Rating">Average Rating</option>
                  <option value="Count" selected>Attendee Count</option>
                </select>
              </div>
        </div>
      </body>

      <!--<script type="text/javascript" src="data.js"></script>-->
      <!--<script type="text/javascript" src="regression.js"></script>-->
     </form>

    <script type="text/javascript">
        function deleteDiv()
        {
            arrayTable = document.getElementById("divTable");
            contenedorSVG = document.getElementById("divSVG");

            father = arrayTable.parentNode;
            father.removeChild(arrayTable);

            mother = contenedorSVG.parentNode;
            mother.removeChild(contenedorSVG);

            createDiv();
        }

        function createDiv()
        {
            var divTable1 = document.createElement("div");
            var divDiagram = document.createElement("div");
            divTable1.setAttribute("id","divTable");
            divDiagram.setAttribute("id","divSVG");
            //midiv.innerHTML = "<p>Este es el contenido de mi div</p>";
            document.body.appendChild(divTable1);
            document.body.appendChild(divDiagram);
            //document.getElementById('donde lo quiero poner').appendChild(midiv);
        }
        function generateNumbers()
        {
            let dataset = [];
            var numbersX = [];
            var numbersY = [];
            for (let i = 1; i < 11; i++)
            {
                dataset.push([document.getElementsByName("x"+i)[0].value, document.getElementsByName("y"+i)[0].value]);
                numbersX.push(document.getElementsByName("x"+i)[0].value);
                numbersY.push(document.getElementsByName("y"+i)[0].value);
            }
            deleteDiv();
            generateTable(numbersX, numbersY);
            plotDispersionDiagram(dataset);
        }

        function generateRandomNumbers()
        {
            let dataset = [];
            var numbersX = [];
            var numbersY = [];
            let numDataPoints = 30;             //Number of dummy data points to create
            let xRange = Math.random() * 1000;  //Max range of new x values
            let yRange = Math.random() * 1000;  //Max range of new y values

            for (let c = 0; c < numDataPoints; c++) //Loop numDataPoints times
            {
                let newNumber1 = Math.round(Math.random() * xRange);    //New random integer
                let newNumber2 = Math.round(Math.random() * yRange);    //New random integer
                numbersX.push(newNumber1);
                numbersY.push(newNumber2);
                dataset.push([newNumber1, newNumber2]);         //Add new number to array
            }
            deleteDiv();
            generateTable(numbersX, numbersY);
            plotDispersionDiagram(dataset);
            combineArrayIntoObject(numbersX, numbersY);
        }

        function generateTable(numbersX, numbersY)
        {
            let table = document.createElement('table'); // Create table.
            table.setAttribute('class', 'article');// Apply CSS for table

            let renglon0 = table.insertRow(0);// Insert New Column for Row1 at index '0'.
            let ren0col1 = renglon0.insertCell(0);
            ren0col1.innerHTML = 'POINT NUMBER';
            let ren0col2 = renglon0.insertCell(1);
            ren0col2.innerHTML = 'X';
            let ren0col3 = renglon0.insertCell(2);
            ren0col3.innerHTML = 'Y';
            let div = document.getElementById('divTable');// Append Table into div.
            div.appendChild(table);

            for (let x = 0; x < numbersX.length; x++)
            {
                let renglonX = table.insertRow(x+1);// Agrega nuevo renglon en x+1
                let rencolX1 = renglonX.insertCell(0);
                rencolX1.innerHTML = x+1; // Agrega Nueva Columna a renglox en el indice 0.

                let rencolX2 = renglonX.insertCell(1);
                rencolX2.innerHTML = numbersX[x];// Agrega Nueva Columna a renglox en el indice 1.

                let rencolX3 = renglonX.insertCell(2);
                rencolX3.innerHTML = numbersY[x];// Agrega Nueva Columna a renglox en el indice 2.
                div.appendChild(table);
            }
        }

        function plotDispersionDiagram(dataset)
        {
            let w = 700;
            let h = 500;
            let padding = 60;
            //Create scale functions
            var xScale = d3.scale.linear()
                                 .domain([0, d3.max(dataset, function(d) { return d[0]; })])
                                 .range([padding, w - padding * 2]);

            var yScale = d3.scale.linear()
                                 .domain([0, d3.max(dataset, function(d) { return d[1]; })])
                                 .range([h - padding, padding]);

            var rScale = d3.scale.linear()
                                 .domain([0, d3.max(dataset, function(d) { return d[1]; })])
                                 .range([2, 5]);

            var formatAsPercentage = d3.format("0.1%");

            //Define X axis
            var xAxis = d3.svg.axis()
                              .scale(xScale)
                              .orient("bottom")
                              .ticks(5)
                              .tickFormat(formatAsPercentage);

            //Define Y axis
            var yAxis = d3.svg.axis()
                              .scale(yScale)
                              .orient("left")
                              .ticks(5)
                              .tickFormat(formatAsPercentage);

            //Create SVG element
            var svg = d3.select("#divSVG")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            //Create circles

            svg.selectAll("circle")
               .data(dataset)
               .enter()
               .append("circle")
               .attr("cx", function(d) {
                    return xScale(d[0]);
               })
               .attr("cy", function(d) {
                    return yScale(d[1]);
               })
               .attr("r", function(d) {
                    return rScale(d[1]);
               });

            //Create labels
            svg.selectAll("text")
               .data(dataset)
               .enter()
               .append("text")
               /*.text(function(d) {
                    return d[2];
               })*/
               .text(function () {
                  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 0;
                  arguments.callee.myStaticVar++;
                  return(arguments.callee.myStaticVar);
                })

               .attr("x", function(d) {
                    return xScale(d[0]);
               })
               .attr("y", function(d) {
                    return yScale(d[1]);
               })
               .attr("font-family", "sans-serif")
               .attr("font-size", "11px")
               .attr("fill", "red");

            svg.append("g") //Create X axis
                .attr("class", "axis")
                .attr("transform", "translate(0," + (h - padding) + ")")
                .call(xAxis);

            svg.append("g") //Create Y axis
                .attr("class", "axis")
                .attr("transform", "translate(" + padding + ",0)")
                .call(yAxis);
        }

        function combineArrayIntoObject(numbersX, numbersY, allData) {
           //let    allData = [];
           let maxLen = numbersX.length > numbersY.length ? numbersX.length : numbersY.length;
           let i = 0;
           while(i < maxLen) {
              let x = numbersX[i] ? numbersX[i]: 0;
              let y = numbersY[i] ? numbersY[i]: 0;
              allData.push({
                  Rating: x,
                  Count: y
            });
            i++;
         }

            return allData;
        }


        var parentId = "#graph-wrapper";
        var animDuration = 1000;
        var margin = {top: 20, right: 50, bottom: 50, left: 100};

        var width = $(parentId).width() - margin.left - margin.right,
            height = $(parentId).height()  - margin.top - margin.bottom;

        var xScale = d3.scale.linear()
            .range([0,width]);

        var yScale = d3.scale.linear()
            .range([height, 0]);

        var line = d3.svg.line();

        var xAxis = d3.svg.axis()
            .scale(xScale)
            .tickSize(-height)
            .tickPadding(8)
            .tickFormat(d3.round)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(yScale)
            .tickSize(-width)
            .tickPadding(8)
            .orient("left");

        var svg = d3.select(parentId).append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
              .attr("id","svg-parent")
            .append("g")
              .attr("id","graph-plane")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + (height) + ")")
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate("  +0+ ",0)")
            .call(yAxis);

        svg.append("path")
            .attr("class","trendline")
            .attr("stroke-width", 1)
            .style("stroke","steelblue")
            .style("fill","none");

        d3.selectAll(".graph-picklist").on("change",function(){
          updateChart(d3.select("#graph-picklist-x")[0][0].value,
                      d3.select("#graph-picklist-y")[0][0].value);
        });


        function getDimensions(x,y, allData){
          var returnX=[];
          var returnY=[];
          var returnPairs = [];
          allData.forEach(function(d){
            var pair = {x: d[x],y: d[y]};
            returnPairs.push(pair);
            returnX.push(d[x]);
            returnY.push(d[y]);
          });
          console.log(typeof(allData));
          return {x:returnX,y:returnY,pairs:returnPairs};
        }

        function updateTitle(x,y){
          //var title = d3.select("#title").text("Linear Regression: "+x+" vs "+y);
          var title = d3.select("#title").text("Regresión Lineal: x vs y");
        }

        // returns slope, intercept and r-square of the line
        //Pulled from http://bl.ocks.org/benvandyke/8459843
        function leastSquares(xSeries, ySeries) {
          var reduceSumFunc = function(prev, cur) { return prev + cur; };

          var xBar = xSeries.reduce(reduceSumFunc) * 1.0 / xSeries.length;
          var yBar = ySeries.reduce(reduceSumFunc) * 1.0 / ySeries.length;

          var ssXX = xSeries.map(function(d) { return Math.pow(d - xBar, 2); })
            .reduce(reduceSumFunc);

          var ssYY = ySeries.map(function(d) { return Math.pow(d - yBar, 2); })
            .reduce(reduceSumFunc);

          var ssXY = xSeries.map(function(d, i) { return (d - xBar) * (ySeries[i] - yBar); })
            .reduce(reduceSumFunc);

          var slope = ssXY / ssXX;
          var intercept = yBar - (xBar * slope);
          var rSquare = Math.pow(ssXY, 2) / (ssXX * ssYY);

          return [slope, intercept, rSquare];
        }
        //http://snipplr.com/view/37687/random-number-float-generator/
        function randomFloatBetween(minValue,maxValue,precision){
            if(typeof(precision) == 'undefined'){
                precision = 2;
            }
            return parseFloat(Math.min(minValue + (Math.random() * (maxValue - minValue)),maxValue).toFixed(precision));
        }

        //"draw" the line with many points respecting the calculated equation
        function calculateLineData(leastSquares,xRange,iterations){
          var returnData = [];
          for(var i=0; i<iterations; i++){
            var randomX = randomFloatBetween(xRange[0],xRange[1]);
            returnData.push({
              xVal:randomX,
              yVal: (randomX*leastSquares[0])+leastSquares[1]
            });
          }
          return returnData;
        }

        function updateChart(x,y){

          updateTitle(x,y);
          //Fetch data
          var records = getDimensions(x,y);

          //Reset scale
          yScale.domain(d3.extent(records.y));
          xScale.domain(d3.extent(records.x));

          //re-assign data (or assign new data)
          var selectedCircles = d3.select("#graph-plane")
                                  .selectAll(".circles")
                                  .data(records.pairs)

          //give a transition on the existing elements
          selectedCircles
            .transition().duration(animDuration)
            .attr("transform",function(d){return "translate("+xScale(d.x)+","+yScale(d.y)+")";})
            .style("fill","steelblue");

          //Append any new elements and transition them as well
          selectedCircles.enter()
                        .append("circle")
                        .attr("class","circles")
                        .attr("r",5)
                        .style("fill","steelblue")
                        .transition().duration(animDuration)
                        .attr("transform",function(d){return "translate("+xScale(d.x)+","+yScale(d.y)+")";});

          //Remove any dom elements which are no longer data bound
          selectedCircles.exit().remove();

          //Update Axes
          d3.select(parentId).select(".x.axis").transition().duration(animDuration).call(xAxis);
          d3.select(parentId).select(".y.axis").transition().duration(animDuration).call(yAxis);

          //Update Regression
          line.x(function(d) { return xScale(d.xVal); })
              .y(function(d) { return yScale(d.yVal); });

          var leastSquaresCoeff = leastSquares(records.x, records.y);
          var lineData = calculateLineData(leastSquaresCoeff,d3.extent(records.x),200);

          var trendline = d3.selectAll(".trendline")
                                .transition().delay(1000).duration(500)
                                .attr("d",line(lineData));

          d3.select("#equation").text(function(){
            return (leastSquaresCoeff[1]<0)?
              "y="+leastSquaresCoeff[0].toFixed(2)+"x"+
                  leastSquaresCoeff[1].toFixed(2)+" rSquared: "+
                  leastSquaresCoeff[2].toFixed(2)
                  :
              "y="+leastSquaresCoeff[0].toFixed(2)+"x"+"+"+
                  leastSquaresCoeff[1].toFixed(2)+" rSquared: "+
                  leastSquaresCoeff[2].toFixed(2);
          });
        }
        $( document ).ready(function() {
          updateChart("Count","Rating");
        });

    </script>
</body>
Uncaught TypeError: Cannot read property 'forEach' of undefined
    at getDimensions (main.html:340)
    at updateChart (main.html:403)
    at HTMLDocument.<anonymous> (main.html:459)
    at i (jquery.min.js:2)
    at Object.fireWith [as resolveWith] (jquery.min.js:2)
    at Function.ready (jquery.min.js:2)
    at HTMLDocument.K (jquery.min.js:2)
getDimensions @ main.html:340
updateChart @ main.html:403
(anonymous) @ main.html:459
i @ jquery.min.js:2
fireWith @ jquery.min.js:2
ready @ jquery.min.js:2
K @ jquery.min.js:2
main.html:267 Uncaught TypeError: Cannot read property 'push' of undefined
    at combineArrayIntoObject (main.html:267)
    at generateRandomNumbers (main.html:136)
    at HTMLButtonElement.onclick (main.html:44)

Этот код генерирует диаграмму дисперсии с помощью d3, но когда я попытался сгенерировать диаграмму линейной регрессии, код завершился неудачно с функцией getDimensions, потому что функция combArrayIntoObject плохо возвращает результат.

0
Kuroi 28 Авг 2017 в 19:52

5 ответов

Лучший ответ

Основное предположение, которое делает эта реализация, состоит в том, что numberX и numberY имеют одинаковую длину . Вы можете настроить его под свои нужды. Создает пустой массив, выполняет цикл для передачи данных в формате объекта, который вы выложили.

let numberX = [10, 22, 33];
let numberY = [34, 44, 9];

let allData = [];

for (let i=0; i < numberX.length; i++) {
  allData.push({
    Rating: numberX[i],
    Count: numberY[i],
    Duration: 0
  })
}

console.log(allData)
1
Christopher Messer 28 Авг 2017 в 16:57

Для получения массива с объектами вы должны отобразить значения в новом объекте.

var numberX = [10, 22, 33],
    numberY = [34, 44, 9],
    allData = numberX.map((Rating, i) =>({ Rating, Count: numberY[i], Duration: 0 }));

console.log(allData);
0
Nina Scholz 28 Авг 2017 в 16:56
let allData = [];
for (let i = 0; i < numberX.length; i++){
    allData.push({
       Rating: numberX[i], 
       Count: numberY[i]
    })
}

Или вот другой вариант:

let allData = numberX.map((item, index) => {
    return {
        Rating: item,
        Count: numberY[index]
    }
})
0
Artem Arkhipov 28 Авг 2017 в 16:58

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

function combineArrayIntoObject(arr1, arr2) {
   let result = [];
   let maxLen = arr1.length > arr2.length ? arr1.length : arr2.length;
   let i = 0;
   while(i < maxLen) {
      let x = arr1[i] ? arr1[i]: 0;
      let y = arr2[i] ? arr2[i]: 0;
      result.push({
          Rating: x,
          Count: y
    });
    i++;
 }

 return result;
}

let x = [10, 22, 33];
let y = [34, 44, 9];

console.log(combineArrayIntoObject(x,y));
1
Piyush Patel 28 Авг 2017 в 17:13

Может быть, что-то вроде этого:

let xObject = {};
xObject.Rating = numberX[0];
xObject.Count = numberX[1];
xObject.Duration= numberX[2];
allData.push(xObject);
0
jonathan.ihm 28 Авг 2017 в 16:56