开发者问题收集

JS:对深层嵌套对象中的所有数字数据进行四舍五入的最佳方法是什么

2021-04-27
160
let data = {
    "enable": false,
    "show": false,
    "showCount": false,
    "work1": {
        "active": true,
        "components": [
            {
                "ID": "xxxxxxxxxxxxxx",
                "filled": true,
                "size": {
                    "width": 50,
                    "height": 50
                },
                "frame": {
                    "x": 333.01068097610835,
                    "y": 223.99888508072843,
                    "width": 50,
                    "height": 50
                }
            },
            {
                "ID": "yyyyyyyyyyyyyy",
                "filled": true,
                "size": {
                    "width": 50,
                    "height": 50
                },
                "frame": {
                    "x": 648.0187300370513,
                    "y": 270.99747284965105,
                    "width": 50,
                    "height": 50
                }
            }
        ],
        "annotations": [
            {
                "ID": "xxxxxxxxxxxxx",
                "points": [
                    {
                        "x": 442.0133605468252,
                        "y": 522.0119330635505
                    },
                    {
                        "x": 443.01438609939953,
                        "y": 521.0129082875666
                    },
                    {
                        "x": 443.01438609939953,
                        "y": 518.0128339596151
                    },
                    {
                        "x": 442.0143605468252,
                        "y": 517.0128091836314
                    },
                    {
                        "x": 442.0143605468252,
                        "y": 515.0127596316637
                    },
                ],
                "tolerance": 1
            }
        ],
        "shapes": []
    }
}

我想将 Math.round() 应用于上述对象中的所有数字数据。 是否有任何库可以帮助我运行循环并对所有数字数据应用四舍五入。 现在,我正在运行循环并将 Math.round 应用于特定键中的数字数据。

例如

"frame": {
    "x": 333.01068097610835,
    "y": 223.99888508072843,
    "width": 50,
    "height": 50
}

应该转换为

"frame": {
    "x": 333,
    "y": 224,
    "width": 50,
    "height": 50
}

我试过这个:

获取“错误:未捕获的 TypeError:无法分配给只读属性”

function reduceSize() {
    for (let key in data) {
        if (typeof (data[key]) === "object") {
            if (data[key]["annotations"] && data[key]["annotations"] instanceof Array) {
                roundOffAnnotations(data[key]["annotations"]);
            }
        }
    }
    console.log(data);
}

function roundOffAnnotations(annotations) {
    if (annotations && annotations instanceof Array) {
        for (let index = 0; index < annotations.length; index++) {
            let annotationAtIndex = annotations[index];
            let roundOffPoints = [];
            if (annotationAtIndex && annotationAtIndex["points"] instanceof Array) {
                for (let point of annotationAtIndex["points"]) {
                    roundOffPoints.push({
                        x: Math.round(point.x),
                        y: Math.round(point.y)
                    });
                }
            }
            annotations[index]["points"] = roundOffPoints; // getting error in this line 
            // Error: Uncaught TypeError: Cannot assign to read only property
        }
    }
}
2个回答

如果您的数据是 JSON 安全的(即没有函数或特殊对象),您可以简单地将其重新编码为 JSON 或从 JSON 重新编码:

newData = JSON.parse(JSON.stringify(data, function (key, val) {
    if (typeof val === 'number')
        return Math.round(val);
    return val;
}))
georg
2021-04-27

您可以进行简单的递归:

  1. 对任何数值进行四舍五入。
  2. 映射任何数组。
  3. 转换任何对象的值。
  4. 保持其他任何内容不变。

无变异:

const round = value => {
  if (typeof value === "number")
    return Math.round(value);
    
  if (Array.isArray(value))
    return value.map(round);
  
  if (typeof value === "object" && value !== null)
    return Object.fromEntries(
      Object.entries(value)
        .map(([k, v]) => [k, round(v)])
      );
      
  return value
}

let data = { "enable": false, "show": false, "showCount": false, "work1": { "active": true, "components": [ { "ID": "xxxxxxxxxxxxxx", "filled": true, "size": { "width": 50, "height": 50 }, "frame": { "x": 333.01068097610835, "y": 223.99888508072843, "width": 50, "height": 50 } }, { "ID": "yyyyyyyyyyyyyy", "filled": true, "size": { "width": 50, "height": 50 }, "frame": { "x": 648.0187300370513, "y": 270.99747284965105, "width": 50, "height": 50 } } ], "annotations": [ { "ID": "xxxxxxxxxxxxx", "points": [ { "x": 442.0133605468252, "y": 522.0119330635505 }, { "x": 443.01438609939953, "y": 521.0129082875666 }, { "x": 443.01438609939953, "y": 518.0128339596151 }, { "x": 442.0143605468252, "y": 517.0128091836314 }, { "x": 442.0143605468252, "y": 515.0127596316637 }, ], "tolerance": 1 } ], "shapes": [] } };

console.log(round(data))

就地修改对象:

const round = value => {
  if (typeof value === "number")
    return Math.round(value);
    
  if (Array.isArray(value))
    value.forEach((el, index) => value[index]= round(el));
  
  if (typeof value === "object" && value !== null)
    Object.entries(value)
      .forEach(([k, v]) => value[k] = round(v))

  return value
}

let data = { "enable": false, "show": false, "showCount": false, "work1": { "active": true, "components": [ { "ID": "xxxxxxxxxxxxxx", "filled": true, "size": { "width": 50, "height": 50 }, "frame": { "x": 333.01068097610835, "y": 223.99888508072843, "width": 50, "height": 50 } }, { "ID": "yyyyyyyyyyyyyy", "filled": true, "size": { "width": 50, "height": 50 }, "frame": { "x": 648.0187300370513, "y": 270.99747284965105, "width": 50, "height": 50 } } ], "annotations": [ { "ID": "xxxxxxxxxxxxx", "points": [ { "x": 442.0133605468252, "y": 522.0119330635505 }, { "x": 443.01438609939953, "y": 521.0129082875666 }, { "x": 443.01438609939953, "y": 518.0128339596151 }, { "x": 442.0143605468252, "y": 517.0128091836314 }, { "x": 442.0143605468252, "y": 515.0127596316637 }, ], "tolerance": 1 } ], "shapes": [] } };

round(data);
console.log(data);
VLAZ
2021-04-27