背景資訊
我有一個物件,其中包含來自網路日志的一些資料。這是它的樣子。
{
"meta_data": {
},
"network_log": [
{
"request_id": "",
"request": {
"url": "https://stackoverflow.com/"
},
"response": {
"status": 200,
"redirectURL": "",
"redirect": []
}
},
{
"request_id": "",
"request": {
"url": "https://stackoverflow.com/page-that-redirects"
},
"response": {
"status": 302,
"redirectURL": "https://stackoverflow.com/another-page-that-redirects",
"redirect": [
{
"request_id": "",
"request": {
"url": "https://stackoverflow.com/another-page-that-redirects"
},
"response": {
"status": 302,
"redirectURL": "https://stackoverflow.com/final-page",
"redirect": [
{
"request_id": "",
"request": {
"url": "https://stackoverflow.com/final-page"
},
"response": {
"status": 200,
"redirectURL": "",
"redirect": []
}
}
]
}
}
]
}
},
{
"request_id": "",
"request": {
"url": "https://stackoverflow.com/page-that-redirects"
},
"response": {
"status": 200,
"redirectURL": "https://stackoverflow.com/page-that-was-redirect-to",
"redirect": []
}
}
]
}
該network_log
元素將始終存在。中的每個專案network_log
都是一個匿名物件,但出于這個問題的目的,我們稱它為ReqResp
物件。
ReqResp.response.redirect
是一個ReqResp
物件串列。它可以在串列中包含 0 個或多個專案。
期望的輸出
我需要導航這個物件并填充所有request_id
欄位。該request_id
欄位將是一個字串值,其格式類似于“Request.Num.Num.Num...”,其中可能存在無限數量的“Num”值,具體取決于物件的深度。“Num”值應該從 1 開始,而不是 0。
以上面的示例為例,這是預期的輸出:
{
"meta_data": {
},
"network_log": [
{
"request_id": "Request.1",
"request": {
"url": "https://stackoverflow.com/"
},
"response": {
"status": 200,
"redirectURL": "",
"redirect": []
}
},
{
"request_id": "Request.2",
"request": {
"url": "https://stackoverflow.com/page-that-redirects"
},
"response": {
"status": 302,
"redirectURL": "https://stackoverflow.com/another-page-that-redirects",
"redirect": [
{
"request_id": "Request.2.1",
"request": {
"url": "https://stackoverflow.com/another-page-that-redirects"
},
"response": {
"status": 302,
"redirectURL": "https://stackoverflow.com/final-page",
"redirect": [
{
"request_id": "Request.2.1.1",
"request": {
"url": "https://stackoverflow.com/final-page"
},
"response": {
"status": 200,
"redirectURL": "",
"redirect": []
}
}
]
}
}
]
}
},
{
"request_id": "Request.3",
"request": {
"url": "https://stackoverflow.com/page-that-redirects"
},
"response": {
"status": 200,
"redirectURL": "https://stackoverflow.com/page-that-was-redirect-to",
"redirect": []
}
}
]
}
我在類似的問題中查找了一些遞回函式,但我很難理解如何跟蹤每個專案的“Num”值。
uj5u.com熱心網友回復:
您可以進行廣度優先搜索或深度優先搜索。兩者都可以迭代或遞回實作。雖然迭代解決方案會更有效,但遞回解決方案可能更容易實作。兩種演算法的復雜性都O(|V| |E|)
在于V
節點E
集和邊集。
使用深度優先搜索的簡單解決方案可能如下所示。
const input = {
meta_data: {},
network_log: [
{
request_id: "",
request: {
url: "https://stackoverflow.com/",
},
response: {
status: 200,
redirectURL: "",
redirect: [],
},
},
{
request_id: "",
request: {
url: "https://stackoverflow.com/page-that-redirects",
},
response: {
status: 302,
redirectURL: "https://stackoverflow.com/another-page-that-redirects",
redirect: [
{
request_id: "",
request: {
url: "https://stackoverflow.com/another-page-that-redirects",
},
response: {
status: 302,
redirectURL: "https://stackoverflow.com/final-page",
redirect: [
{
request_id: "",
request: {
url: "https://stackoverflow.com/final-page",
},
response: {
status: 200,
redirectURL: "",
redirect: [],
},
},
],
},
},
],
},
},
{
request_id: "",
request: {
url: "https://stackoverflow.com/page-that-redirects",
},
response: {
status: 200,
redirectURL: "https://stackoverflow.com/page-that-was-redirect-to",
redirect: [],
},
},
],
};
const depthFirstSearchRec = (input, path = []) => {
return input.map((req, idx) => {
const newPath = [...path, idx 1]
req.request_id = `Request.${newPath.join(".")}`
const redirect = req.response.redirect;
if (
redirect &&
Array.isArray(redirect) &&
redirect.length !== 0
) req.response.redirect = depthFirstSearchRec(req.response.redirect, newPath);
return req;
})
};
// this mutates the input! NOT immutable!
depthFirstSearchRec(input.network_log);
console.log(JSON.stringify(input, null, 4));
.as-console-wrapper { max-height: 100% !important; top: 0; }
請注意:此解決方案會改變輸入!
uj5u.com熱心網友回復:
這是一個不可變的方法,回傳一個新物件:
const convertLog = (xs, path = "Request") =>
xs .map (({request_id, response: {redirect, ...more}, ...rest}, i) => ({
request_id: `${path}.${i 1}`,
...rest,
response: {
...more,
redirect: convertLog (redirect, `${path}.${i 1}`)
}
}))
const convert = ({network_log, ...rest}) =>
({...rest, network_log: convertLog (network_log)})
const data = {"meta_data": {}, "network_log": [{"request": {"url": "https://stackoverflow.com/"}, "request_id": "", "response": {"redirect": [], "redirectURL": "", "status": 200}}, {"request": {"url": "https://stackoverflow.com/page-that-redirects"}, "request_id": "", "response": {"redirect": [{"request": {"url": "https://stackoverflow.com/another-page-that-redirects"}, "request_id": "", "response": {"redirect": [{"request": {"url": "https://stackoverflow.com/final-page"}, "request_id": "", "response": {"redirect": [], "redirectURL": "", "status": 200}}], "redirectURL": "https://stackoverflow.com/final-page", "status": 302}}], "redirectURL": "https://stackoverflow.com/another-page-that-redirects", "status": 302}}, {"request": {"url": "https://stackoverflow.com/page-that-redirects"}, "request_id": "", "response": {"redirect": [], "redirectURL": "https://stackoverflow.com/page-that-was-redirect-to", "status": 200}}]}
console .log (convert (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我們的主函式convert
處理物件的外殼,只復制除 之外的所有屬性network_log
,它委托給我們的重要函式convertLog
。此遞回函式將redirect
在屬性陣列上呼叫response
,傳遞當前路徑(例如Request.2.1
)并跟蹤當前索引。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/507854.html
標籤:javascript json 递归 遍历