首页 > 解决方案 > 用于创建 JSON 对象而不复制键的 JavaScript 循环

问题描述

需要一些关于如何通过循环遍历数组而不复制某些键来创建 JSON 对象的建议

我得到了一个数组,我需要将其拆分为一个对象,但不复制其中一个键

例如:

var myArray = [
    "name/ServiceV1/20190201/1/index.html",
    "name/ServiceV2/20190201/1/index.html",
    "name/ServiceV2/20190201/2/index.html",
    "name/ServiceV2/20190201/3/index.html",
    "name/ServiceV2/20190203/3/index.html",
    "name/ServiceV3/20190213/1/index.html"
];

退货

[
    {
        "name": {
            "ServiceV1": {
                "20190201": {
                    "1": "index.html"
                }
            },
            "ServiceV2": {
                "20190201": {
                    "1": "index.html",
                    "2": "index.html",
                    "3": "index.html"
                },
                "20190203": {
                    "1": "index.html"
                },
            },
            "ServiceV3": {
                "20190213": {
                    "1": "index.html"
                },
            }
        }
    }
]

我怎样才能让它工作?下面的代码是我已经拥有的

var jsonify = function() {
  var myArray = [
    "name/ServiceV1/20190201/1/index.html",
    "name/ServiceV2/20190201/1/index.html",
    "name/ServiceV2/20190201/2/index.html",
    "name/ServiceV2/20190201/3/index.html",
    "name/ServiceV2/20190203/3/index.html",
    "name/ServiceV3/20190213/1/index.html"
  ];
  let end = [];

  // Loop through all the myArray items
  for (let i = 0; i < myArray.length; i++) {
    var itemparts = myArray[i].split("/");

    var newObject = {};
    var value = itemparts.pop();
    while (itemparts.length) {
      var obj = {};
      if (newObject.hasOwnProperty(itemparts.pop())) {
        return;
      } else {
        newObject[itemparts.pop()] = value;
      }
      obj[itemparts.pop()] = value;
      value = obj;
    }
    end.push(value);
  }

  // return the results
  return end;
};

但这会返回:

[
  {
    "name": {
      "ServiceV1": {
        "20190201": {
          "1": "index.html"
        }
      }
    }
  },
  {
    "name": {
      "ServiceV2": {
        "20190201": {
          "8": "index.html"
        }
      }
    }
  },
  {
    "name": {
      "ServiceV2": {
        "20190201": {
          "9": "index.html"
        }
      }
    }
  },
  {
    "name": {
      "ServiceV2": {
        "20190201": {
          "17": "index.html"
        }
      }
    }
  }
]

所以我有点不知道下一步该去哪里

标签: javascript

解决方案


斯蒂芬,您正在创建新对象并将它们推到数组的末尾,这总是会导致列表变得越来越长。

您最初的措辞已经暗示出了什么问题:“如何创建 JSON 对象”

与其创建新对象以添加到列表中,不如只使用您修改/更新的一个对象。请记住,对象是 JavaScript 中的引用。

我在这个例子中使用了递归,因为它非常适合。

// WARNING: This code assumes a very specific text structure.
// It's for a specific use case, not a generic solution. Details in comments below.
const result = {};  // References are immutable in JS' const, not values.
const texts = [
    'a/b/c/file1.html',
    'b/c/d/file2.html',
    'a/b/e/file3.html'
];

function gluePartsToObject(obj, parts) {
    // End of the line.
    if (parts.length === 1) return parts.shift();

    // We've still got some ways to go.
    const part = parts.shift();
    if (obj.hasOwnProperty(part)) {
        // Re-use object reference.
        obj[part] = gluePartsToObject(obj[part], parts);
    } else {
        // Don't have an object yet to reference, create one.
        obj[part] = gluePartsToObject({}, parts);
    }
    
    return obj;
}

// ES2015 "of". Can be replaced with a regular loop for compatibility.
for (text of texts) {
    let parts = text.split('/');
    gluePartsToObject(result, parts);
}

console.log(result);


推荐阅读