我是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而失败,因为函数combineArrayIntoObject没有很好地返回结果。
答案 0 :(得分:1)
此实施的关键假设是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 :(得分:1)
解决问题的更好的功能方法 如果没有找到值,则不需要相同长度的数组,它将分配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));
答案 2 :(得分:0)
也许是这样的:
let xObject = {};
xObject.Rating = numberX[0];
xObject.Count = numberX[1];
xObject.Duration= numberX[2];
allData.push(xObject);
答案 3 :(得分:0)
为了使用对象来设置数组,可以将值映射到新对象中。
var numberX = [10, 22, 33],
numberY = [34, 44, 9],
allData = numberX.map((Rating, i) =>({ Rating, Count: numberY[i], Duration: 0 }));
console.log(allData);
答案 4 :(得分:0)
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]
}
})