带有嵌套for循环的Javascript多维数组-无法正常工作
Posted
技术标签:
【中文标题】带有嵌套for循环的Javascript多维数组-无法正常工作【英文标题】:Javascript Multi-Dimensional Array with nested for Loop - Not working right 【发布时间】:2022-01-18 04:57:34 【问题描述】:我有一个多维数组,我用两个 for 循环遍历它。如果满足某些条件,即 j 的值为 0,那么我想运行代码以将附加字段插入到数组中。如果 j 大于 0,我想运行一个函数,然后将此更新应用于数组。
我的问题是这个。循环似乎工作得很好,但它似乎在某个时候更新了数组的错误部分,我不确定为什么。我提供了一个测试数据集和我所指的代码。根据我在“calcCrowFliesTripMiles”函数中的代码,“legCrowFliesDistance”的 j=0 时的值应该等于“distanceFromKage”,但事实并非如此。我不确定这里发生了什么,但我似乎无法弄清楚。
function toRad (Value)
return Value * Math.PI / 180;
function calcCrow (lat1, lon1, lat2, lon2)
var R = 6371; // km
var dLat = toRad(lat2 - lat1);
var dLon = toRad(lon2 - lon1);
var lat1 = toRad(lat1);
var lat2 = toRad(lat2);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
function calcCrowFliesTripMiles (combinations)
var stopArray = [];
stopArray = [...combinations];
for (let i = 0; i < stopArray.length; i++)
for (let j = 0; j < stopArray[i].length; j++)
if (j === 0)
stopArray[i][j].legCrowFliesDistance = stopArray[i][j].distanceFromKage;
else
stopArray[i][j].legCrowFliesDistance = calcCrow(stopArray[i][(j - 1)].attributes[0].ucmlLat, stopArray[i][(j - 1)].attributes[0].ucmlLng, stopArray[i][j].attributes[0].ucmlLat, stopArray[i][j].attributes[0].ucmlLng);
return stopArray;
var testArray = [
[
'ShipLOC': 'SANCO',
'attributes': [
'ucmlLat': '43.881431',
'ucmlLng': '-92.496931',
],
'totalLocationProductLength': 184,
'distanceFromKage': 159.39214641507564,
], [
'ShipLOC': 'MALVESEQ',
'attributes': [
'ucmlLat': '40.936476',
'ucmlLng': '-72.653116',
],
'totalLocationProductLength': 96,
'distanceFromKage': 1691.1958136706187,
], [
'ShipLOC': 'MONTRA',
'attributes': [
'ucmlLat': '42.286261',
'ucmlLng': '-71.598679',
],
'totalLocationProductLength': 476,
'distanceFromKage': 1719.5409479837117,
], [
'ShipLOC': 'SANCO',
'attributes': [
'ucmlLat': '43.881431',
'ucmlLng': '-92.496931',
],
'totalLocationProductLength': 184,
'distanceFromKage': 159.39214641507564,
,
'ShipLOC': 'MALVESEQ',
'attributes': [
'ucmlLat': '40.936476',
'ucmlLng': '-72.653116',
],
'totalLocationProductLength': 96,
'distanceFromKage': 1691.1958136706187,
], [
'ShipLOC': 'SANCO',
'attributes': [
'ucmlLat': '43.881431',
'ucmlLng': '-92.496931',
],
'totalLocationProductLength': 184,
'distanceFromKage': 159.39214641507564,
,
'ShipLOC': 'MONTRA',
'attributes': [
'ucmlLat': '42.286261',
'ucmlLng': '-71.598679',
],
'totalLocationProductLength': 476,
'distanceFromKage': 1719.5409479837117,
], [
'ShipLOC': 'MALVESEQ',
'attributes': [
'ucmlLat': '40.936476',
'ucmlLng': '-72.653116',
],
'totalLocationProductLength': 96,
'distanceFromKage': 1691.1958136706187,
,
'ShipLOC': 'MONTRA',
'attributes': [
'ucmlLat': '42.286261',
'ucmlLng': '-71.598679',
],
'totalLocationProductLength': 476,
'distanceFromKage': 1719.5409479837117,
], [
'ShipLOC': 'SANCO',
'attributes': [
'ucmlLat': '43.881431',
'ucmlLng': '-92.496931',
],
'totalLocationProductLength': 184,
'distanceFromKage': 159.39214641507564,
,
'ShipLOC': 'MALVESEQ',
'attributes': [
'ucmlLat': '40.936476',
'ucmlLng': '-72.653116',
],
'totalLocationProductLength': 96,
'distanceFromKage': 1691.1958136706187,
,
'ShipLOC': 'MONTRA',
'attributes': [
'ucmlLat': '42.286261',
'ucmlLng': '-71.598679',
],
'totalLocationProductLength': 476,
'distanceFromKage': 1719.5409479837117,
],
];
console.log(calcCrowFliesTripMiles(testArray));
.as-console-wrapper min-height: 100%!important; top: 0;
编辑: 这是另一个要测试的数据集,它稍微小一些,是我正在提取的实际数据的极简版本。当我使用 testArray 和使用我的实际数组时得到的结果是不同的。当我创建测试数组时,我从控制台复制实际数据,删除该函数中未使用的一些属性字段,然后将数据分配给数组。我不知道为什么两者的结果会不同,因为数据看起来完全一样,不包括附加属性字段。
数据:
[
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
]
]
When I run the code after assigning the above data to testArray, these are the results I get:
[
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
]
]
使用 testArray 时的结果:
[
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931"
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
"legCrowFliesDistance": 159.39214641507564
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116"
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
"legCrowFliesDistance": 1691.1958136706187
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931"
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
"legCrowFliesDistance": 159.39214641507564
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116"
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
"legCrowFliesDistance": 1657.5070148937111
]
]
使用实际数据时的结果(删除了大部分属性字段):
[
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
"legCrowFliesDistance": 159.39214641507564
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
"legCrowFliesDistance": 1657.5070148937111
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
"legCrowFliesDistance": 159.39214641507564
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187,
"legCrowFliesDistance": 1657.5070148937111
]
]
【问题讨论】:
我更新了我的帖子。我相信这是重现问题的极简主义。 【参考方案1】:我查看了您的代码,对我来说,父数组中每个数组的第一个元素具有与legCrowFliesDistance
相同的值。我发现您试图在您的 calcCrow
函数中重新声明变量 lat1
和 lat2
。我将它们重命名为lat1rad
和lat2rad
,它似乎正如你所描述的那样工作。我不确定这是否是您正在寻找的修复程序,但我没有其他输出可以与之比较。
这是代码:
let testArray = [
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187
],
[
"ShipLOC": "MONTRA",
"attributes": [
"ucmlLat": "42.286261",
"ucmlLng": "-71.598679",
],
"totalLocationProductLength": 476,
"distanceFromKage": 1719.5409479837117,
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564,
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564
,
"ShipLOC": "MONTRA",
"attributes": [
"ucmlLat": "42.286261",
"ucmlLng": "-71.598679",
],
"totalLocationProductLength": 476,
"distanceFromKage": 1719.5409479837117
],
[
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187
,
"ShipLOC": "MONTRA",
"attributes": [
"ucmlLat": "42.286261",
"ucmlLng": "-71.598679",
],
"totalLocationProductLength": 476,
"distanceFromKage": 1719.5409479837117
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187
,
"ShipLOC": "MONTRA",
"attributes": [
"ucmlLat": "42.286261",
"ucmlLng": "-71.598679",
],
"totalLocationProductLength": 476,
"distanceFromKage": 1719.5409479837117
],
[
"ShipLOC": "SANCO",
"attributes": [
"ucmlLat": "43.881431",
"ucmlLng": "-92.496931",
],
"totalLocationProductLength": 184,
"distanceFromKage": 159.39214641507564
,
"ShipLOC": "MALVESEQ",
"attributes": [
"ucmlLat": "40.936476",
"ucmlLng": "-72.653116",
],
"totalLocationProductLength": 96,
"distanceFromKage": 1691.1958136706187
,
"ShipLOC": "MONTRA",
"attributes": [
"ucmlLat": "42.286261",
"ucmlLng": "-71.598679",
],
"totalLocationProductLength": 476,
"distanceFromKage": 1719.5409479837117
]
];
console.log(calcCrowFliesTripMiles(testArray));
function calcCrowFliesTripMiles (combinations)
let stopArray = [];
stopArray = [...combinations];
for (let i =0; i < stopArray.length; i++)
for (let j=0; j < stopArray[i].length; j++)
if (j===0)
stopArray[i][j].legCrowFliesDistance = stopArray[i][j].distanceFromKage
else
stopArray[i][j].legCrowFliesDistance = calcCrow(
stopArray[i][(j -1)].attributes[0].ucmlLat,
stopArray[i][(j -1)].attributes[0].ucmlLng,
stopArray[i][j].attributes[0].ucmlLat,
stopArray[i][j].attributes[0].ucmlLng
);
return stopArray;
function calcCrow(lat1, lon1, lat2, lon2)
const R = 6371; // km
let dLat = toRad(lat2-lat1);
let dLon = toRad(lon2-lon1);
let lat1rad = toRad(lat1);
let lat2rad = toRad(lat2);
let a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1rad) * Math.cos(lat2rad);
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
let d = R * c;
return d;
// Converts numeric degrees to radians
function toRad(Value)
return Value * Math.PI / 180;
希望这会有所帮助!
编辑:
这是我在控制台中得到的:
[
[
"ShipLOC":"SANCO",
"attributes":[
"ucmlLat":"43.881431",
"ucmlLng":"-92.496931"
],
"totalLocationProductLength":184,
"distanceFromKage":159.39214641507564,
"legCrowFliesDistance":159.39214641507564
],
[
"ShipLOC":"MALVESEQ",
"attributes":[
"ucmlLat":"40.936476",
"ucmlLng":"-72.653116"
],
"totalLocationProductLength":96,
"distanceFromKage":1691.1958136706187,
"legCrowFliesDistance":1691.1958136706187
],
[
"ShipLOC":"MONTRA",
"attributes":[
"ucmlLat":"42.286261",
"ucmlLng":"-71.598679"
],
"totalLocationProductLength":476,
"distanceFromKage":1719.5409479837117,
"legCrowFliesDistance":1719.5409479837117
],
[
"ShipLOC":"SANCO",
"attributes":[
"ucmlLat":"43.881431",
"ucmlLng":"-92.496931"
],
"totalLocationProductLength":184,
"distanceFromKage":159.39214641507564,
"legCrowFliesDistance":159.39214641507564
,
"ShipLOC":"MALVESEQ",
"attributes":[
"ucmlLat":"40.936476",
"ucmlLng":"-72.653116"
],
"totalLocationProductLength":96,
"distanceFromKage":1691.1958136706187,
"legCrowFliesDistance":1657.5070148937111
],
[
"ShipLOC":"SANCO",
"attributes":[
"ucmlLat":"43.881431",
"ucmlLng":"-92.496931"
],
"totalLocationProductLength":184,
"distanceFromKage":159.39214641507564,
"legCrowFliesDistance":159.39214641507564
,
"ShipLOC":"MONTRA",
"attributes":[
"ucmlLat":"42.286261",
"ucmlLng":"-71.598679"
],
"totalLocationProductLength":476,
"distanceFromKage":1719.5409479837117,
"legCrowFliesDistance":1701.836066634145
],
[
"ShipLOC":"MALVESEQ",
"attributes":[
"ucmlLat":"40.936476",
"ucmlLng":"-72.653116"
],
"totalLocationProductLength":96,
"distanceFromKage":1691.1958136706187,
"legCrowFliesDistance":1691.1958136706187
,
"ShipLOC":"MONTRA",
"attributes":[
"ucmlLat":"42.286261",
"ucmlLng":"-71.598679"
],
"totalLocationProductLength":476,
"distanceFromKage":1719.5409479837117,
"legCrowFliesDistance":173.81078287083193
],
[
"ShipLOC":"SANCO",
"attributes":[
"ucmlLat":"43.881431",
"ucmlLng":"-92.496931"
],
"totalLocationProductLength":184,
"distanceFromKage":159.39214641507564,
"legCrowFliesDistance":159.39214641507564
,
"ShipLOC":"MALVESEQ",
"attributes":[
"ucmlLat":"40.936476",
"ucmlLng":"-72.653116"
],
"totalLocationProductLength":96,
"distanceFromKage":1691.1958136706187,
"legCrowFliesDistance":1657.5070148937111
,
"ShipLOC":"MONTRA",
"attributes":[
"ucmlLat":"42.286261",
"ucmlLng":"-71.598679"
],
"totalLocationProductLength":476,
"distanceFromKage":1719.5409479837117,
"legCrowFliesDistance":173.81078287083193
],
[
"ShipLOC":"SANCO",
"attributes":[
"ucmlLat":"43.881431",
"ucmlLng":"-92.496931"
],
"totalLocationProductLength":184,
"distanceFromKage":159.39214641507564,
"legCrowFliesDistance":159.39214641507564
,
"ShipLOC":"MALVESEQ",
"attributes":[
"ucmlLat":"40.936476",
"ucmlLng":"-72.653116"
],
"totalLocationProductLength":96,
"distanceFromKage":1691.1958136706187,
"legCrowFliesDistance":1657.5070148937111
,
"ShipLOC":"MONTRA",
"attributes":[
"ucmlLat":"42.286261",
"ucmlLng":"-71.598679"
],
"totalLocationProductLength":476,
"distanceFromKage":1719.5409479837117,
"legCrowFliesDistance":173.81078287083193
]
]
【讨论】:
【参考方案2】:经过大量故障排除后,我想出了一个可行的解决方案,但我不知道它为什么有效,只是它确实有效。我使用 JSON.stringify 将我的数据转换为 JSON,然后使用 JSON.parse 解析它,然后之前无法正常工作的函数正常工作。这是我唯一更改的代码行。
原代码:
console.log(calcCrowFliesTripMiles(this.state.allCombinations))
新代码:
console.log(calcCrowFliesTripMiles(JSON.parse(JSON.stringify(this.state.allCombinations))))
【讨论】:
我认为这个解决方案可能有效,因为调用JSON.parse
和 JSON.stringify
正在创建无法变异的原始克隆。 stopArray = [...combinations];
行正在创建一个浅拷贝,这意味着嵌套数组仍然通过引用传递,因此它们可以被变异。
那么,如果我使用 stopArray = 组合来代替它,它是否也不能被突变?
不,因为它也会通过引用传递。我认为当数组或对象太深时,处理其值的唯一方法是执行深度克隆。使用 json stringify 进行 Json 解析是执行深度克隆的一种方式(尽管并非对所有情况都完美),因此在不知情的情况下,您可能已经完成了您能做的最好的事情之一
谢谢,我相信这将在整个项目中以数据格式的方式发生。我现在知道发生了什么!
感谢您的链接。我想我需要以不同的方式做到这一点。我向 JSON.stringify() 传递了一个非常大的对象数组,它出现了“RangeError: Invalid String Length”,这基本上意味着我的 JSON 字符串太长并且无法对其进行字符串化。我应该使用上面链接中的示例吗?看起来我可以使用 jQuery 或纯 javascript 来进行深度克隆。我还在网上读到你可以使用文件流媒体处理 JSON,但我没有文件流媒体的经验,我不确定它们是如何工作的。以上是关于带有嵌套for循环的Javascript多维数组-无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章