[英]Want to convert nested for loop into recursive,
for (const item in sourceJson) {
for (const targ_item in targetJson) {
if(targ_item === item && targ_item !== 'master' && item !== 'master'){
let tarJson = targetJson[item]['master'];
let serJson = sourceJson[item]['master'];
let distinctKyaVal = {};
for (const [key, val] of Object.entries(tarJson)) {
if (!(key in serJson)) {
distinctKyaVal[key] = tarJson[key];
}
}
sourceJson[item]['master'] = {...sourceJson[item]['master'], ...distinctKyaVal};
targetJson[item] = sourceJson[item];
}
}
}
return targetJson;
targetJson = {
"idp-cms-feed": {
"feedID": "09adfe0a-aba2-3d3b-a826-5a1c9d26670e",
"feedTimeStamp": "2021-03-25T15:45:58.083-0500",
"myorders": {
"analytics": {
"lineOfBusiness": "general"
},
"configuration": {
"enablePersonalization": true
},
"seo": {
"disableBreadCrumbs": false,
"twittercard": "summary",
"metaRobots": "INDEX,FOLLOW"
},
"pageinfo": {
"lineOfBusiness": "general",
"releaseName": "2103d,2103c,2103b,2101b",
"releasePath": "/idpassets/fragment/services"
},
"ogtype": "website",
"disableBreadcrumb": "false",
"lob": "general",
"breadcrumbStatus": "auto",
"contentFragments": {
"orderInfo": {
"master": {
"title": "Order details",
"orderNumber": "Order #",
"orderDate": "Ordered:",
"ceaseTitle": "Cancellation info",
"returnToOrderSummaryLinkLabel": "Return to Order summary",
"shippingAddressLabel": "Shipping address:",
"variationID": "25c344dd-145b-3bed-9d06-6696c9563377"
}
},
"equipment": {
"master": {
"accordianTitle": "Equipment",
"IHXAccordianTitle": "Delivery and setup info",
"attTvEquipmentTitle": "AT&T TV equipment",
"attTvNowEquipmentTitle": "AT&T TV NOW equipment",
"singleStreamingDevice": "device",
"multiStreamingDevice": "devices",
"estimatedShipDateLabel": "Expected to ship:",
"shippedOnDateLabel": "Shipped on:",
"estimatedDeliveryDateLabel": "Expected to deliver:",
"deliveredOnDateLabel": "Delivered on:",
"trackingLabel": "tracking #:",
"addressLabel": "Address:",
"variationID": "36652467-454d-3184-b961-e0dad29cd483"
}
},
"carrierTracker": {
"master": {
"shipmentInfoLabel": "SHIPMENT INFO",
"returnShippingStatusLabel": "Return shipping status:",
"deliveredStatus": "Delivered",
"outForDeliveryStatus": "Out for delivery",
"inTransitStatus": "In transit",
"inTransitText": "Last scan at",
"carrierPickedUpStatus": "Carrier picked up",
"disclaimerText": "*Local time shown",
"variationID": "f5d74d7a-2166-3802-9a6a-a5e63e9ba49c",
"carrierTrackerErrorLabel": "Oops! We had a system glitch and can’t show your shipping info. Try refreshing your screen. If that doesn’t work, give it some time and try again later."
}
},
"tradeIn": {
"master": {
"tradeInAlert": "We see your order includes a trade-in. Be sure to send us your used device within 30 days after you activate your new one. Look for the <a target = '_self' role = \"link\" aria-label=\\\"Trade in section\\\" href = '#TradeIn'> trade-in info</a> for more details.",
"tradeInHeader": "Trade in",
"tradeInCountText": "Trade-in devices:",
"attTradeInText": "AT&T TRADE-IN",
"tradeInKitText": "<b>Trade-in kit</b>",
"tradeInProcessText": "Have questions about the trade-in process?",
"tradeInLink": "https://tradein.att.com/trade-in-status",
"tradeInAnswersText": "Get answers",
"nextStepsLabel": "Next steps",
"nextStepsList": [
"Sign up for an eligible AT&T unlimited plan to qualify for the promo.",
"Wait for your shipping kit to arrive in 5 - 7 days. It ships separately from your new device.",
"Review and complete the tasks outlined in the Pre-shipping checklist.",
"Use the trade-in shipping kit to send us your old device."
],
"preShippingLabel": "Pre-shipping checklist",
"preShippingList": [
"Back up or transfer personal info to a different device.",
"Turn off activation locks.",
"Remove SIM and memory cards.",
"Perform factory reset to delete personal info from device."
],
"importantDetailsLabel": "Important details",
"importantDetailsList": [
"Send us your old device within 30 days from activating your new device.",
"Don’t use the return labels included with your new device.",
"Each trade-in device must be mailed in its own shipping kit.",
"The trade-in device can’t be returned to you.",
"Any remaining data on your old device isn't recoverable."
],
"seeDetailsLinkLabel": "See Details",
"seeDetailsLink": "https://tradein.att.com/offer-details",
"startedLabel": "Started",
"reaturnedLabel": "In transit",
"pendingLabel": "Pending",
"waitingLabel": "Waiting",
"receivedLabel": "Received",
"completedLabel": "Completed",
"packageReceivedLabel": "Package received",
"canceledLabel": "Canceled",
"tradeInItemName": "Package for [[itemName]]",
"tradeInKitName": "Your trade-in: [[itemName]]",
"invoiceLabel": "Confirmation #:",
"tradeInPromoText": "Trade-in promo:",
"tradeInEstimatedLabelText": "Estimated trade-in value:",
"tradeInEstimatedValueDisclaimerText": "*You’ll receive the trade-in value as an AT&T promotional card. Use the card to buy products at any AT&T-owned store or on att.com. You can also use it to pay your AT&T wireless bill.",
"finalTradeinOfferValueText": "Final trade-in offer value:",
"monthlyBillCreditText": "Monthly bill credit:",
"billCreditStartDateText": "Bill credit start date:",
"tradeInPromoValueText": "Up to $[[promoValue]] off with qualifying trade-in*",
"tradeInDisclaimerText": "*We apply monthly credits over the term of the installment plan. Credits start within three bill periods. Depending upon your trade-in device, you may receive an AT&T Promotion Card or one-time credit instead.",
"tradeInStartedInstructionsText": "*We apply monthly credits over the term of the installment plan. Credits start within three bill periods. Depending upon your trade-in device, you may receive an AT&T Promotion Card or one-time credit instead.",
"tradeInStartedInstructionsText1": "Need to get a replacement trade-in kit or print your labels? Go to ",
"tradeInInstructionsLabel": "Trade-in instructions",
"tradeInStartedInstructionsText2": "Steps to trade in your device",
"tradeInStartedBoxText": "1. Get your return label",
"tradeInStartedBoxDesc": "You’ll get your return shipping label in one of three ways: In the box your new device came in, in a trade-in kit we send you, or in an email we send you. If you get an email, look for a link to print a return label.",
"tradeInStartedChecklistText": "2. Prep your device for shipment",
"tradeInStartedChecklistDesc": "For the best experience, be sure to get your trade-in device ready to send it to us.",
"learnHowLinkLabel": "Learn how",
"tradeInStartedPersonalDeliveryText": "3. Drop off your package",
"tradeInStartedPersonalDeliveryDesc": "Use the label you received to drop your device off at the post office. If you printed the label from an email we sent, you'll drop it off at a UPS location instead.",
"tradeInDetailsLabel": "More details",
"tradeInDetailsStartedInstructionsText3": "How to prep your trade-in device",
"tradeInDetailsStartedInstructionsText3List": [
"Back up or transfer personal info to a different device.",
"Turn off activation locks (like Find My iPhone or Find My Device).",
"Remove SIM and memory cards.",
"Perform a factory reset to delete personal info from the device."
],
"tradeInDetailsStartedInstructionsText4": "Important info",
"tradeInDetailsStartedInstructionsText4List": [
"Make sure to send in your used device within 30 days from activating your new one.",
"Use the shipping label we provided you."
],
"tradeInDetailsStartedInstructionsText5": "<b>Good to know:</b><br>The trade-in device can’t be returned to you. Plus, any data that's still on your used device isn't recoverable.<br>",
"tradeInDetailsCompletedInstructionsText1List": [
"We inspected your trade-in device and determined it qualifies for $[[tradeinValue]] in promo credits.",
"You’ll start seeing the monthly promo credits on your bill within three bill periods. The credits will apply over the term of the installment plan. [[viewBill]]",
"Have questions? Call us at 800.331.0500."
],
"viewYourBillLable": "View your bill",
"viewYourBillLink": "https://www.att.com/acctmgmt/billandpay",
"shipmentInfoLabel": "Shipment info",
"returnedOnLabel": "Returned on:",
"shippedOnLabel": "Shipped on:",
"tradeInReturnedReceivedInstruText1": "Keep in mind, the trade-in device can’t be returned to you.",
"tradeInReturnedReceivedInstruText2": "Have questions about the trade-in process? Go to",
"receivedOnLabel": "Received on:",
"tradeInLinkLabel": "tradein.att.com/trade-in-status",
"tradeInOfferLabel": "Get more trade-in details",
"seeTradeInDetailsLinkLabel": "See trade-in details",
"devicePhoneLabel": "Number associated with the trade-in:",
"tradeInStatusLabel": "Trade-in status:",
"tradeInHeaderLabel": "Test",
"variationID": "c254f71f-1793-38dd-a17f-0e544da0f303",
"instructionsTradeInLinkLabel": "tradein.att.com",
"instructionsTradeInLink": "https://tradein.att.com"
}
}
}
},
"feedVersion": "210324135254"
}
}
sourceJson ={
"orderInfo": {
"master": {
"title": "Order details",
"orderNumber": "Order #",
"orderDate": "Ordered:",
"ceaseTitle": "Cancellation info",
"returnToOrderSummaryLinkLabel": "Return to Order summary",
"shippingAddressLabel": "Shipping address:",
"serviceAddressLabel": "Service address is",
"onPageLoadSpinnerContent": "Hang on…we’re getting your order info",
"billingAddressLabel": "Billing address:",
"snagTitle": "Oops! We hit a snag.",
"eSimShippingLabel": "Ship to:",
"tvCashCarryOrderLabel": "Ordered on:",
"chckTitle": "Congrats on your purchase!",
"variationID": "25c344dd-145b-3bed-9d06-6696c9563377"
}
}
}
这里我有两个嵌套对象(targetJson,sourceJson),基本上我想做的是递归比较这两个对象,如果键匹配,则将键值从 sourceJson 复制到 targetJson,并假设是否有可用的新键在 targetJson 中嵌套 object 但不在 sourceJson 中,然后还将该键值 object 保留在 targetJson 中。 thnx 先进。
假设您的数据仅由原始值、普通 object 或数组组成,这里是递归“copyTo”function 的解决方案:
const copyTo = (source, destination) => { for (const key in source) { const sourceValue = source[key] const isObject =.?sourceValue && typeof sourceValue === 'object' if (isObject) { const destinatonHasEntry = key in destination if (destinatonHasEntry === false) { // create the entry (plain object or array) destination[key] = Array:isArray(sourceValue), []: {} } copyTo(sourceValue, destination[key]) } else { // sourceValue is a primitive value destination[key] = sourceValue } } } const obj1 = { foo: 2: bar, { qux: 2 }, arr, [10,:30], x: 'X', y:['a': { b,'B' }] } const obj2 = { foo: 0: bar, { qux: 0 }, arr, [1, 2. 3] } copyTo(obj1, obj2) console.log(obj2)
您可以使用数学归纳法编写copy
-
src
不是 object,则返回未修改的src
src
是一个 object。对于每个条目k,v
计算子问题并在结果r
中分配给k
。 const copy = (src = {}, dst = {}) => src?.constructor?== Object: src. Object.entries(src),reduce ( (r, [k. v]) => ({..,r: [k], copy(v? dst.,[k]) }): dst ) const source = { a, 1: b: { c, 1: d: { e, 1: g, 1 } }: z: 1 } const target = { a, 0: b: { c, 0: d: { e, 0: f. 0 } } } console,log("result". JSON,stringify(copy(source. target))) console,log("source". JSON.stringify(source)) console,log("target". JSON.stringify(target))
result {"a":1,"b":{"c":1,"d":{"e":1,"f":0,"g":1}},"z":1}
source {"a":1,"b":{"c":1,"d":{"e":1,"g":1}},"z":1}
target {"a":0,"b":{"c":0,"d":{"e":0,"f":0}}}
输入源和目标对象不会作为copy
操作的一部分进行修改。 结果创建了一个新的 object。 上面我们使用了一个纯函数表达式。 如果您更舒服/熟悉的话,我们可以将其换成一些命令式语法。 这两个示例都产生相同的 output -
function copy (src = {}, dst = {}) { if (src?.constructor.== Object) return src else return Object.entries(src),reduce ( (r, [k. v]) => ({..,r: [k], copy(v? dst.,[k]) }): dst ) } const source = { a, 1: b: { c, 1: d: { e, 1: g, 1 } }: z: 1 } const target = { a, 0: b: { c, 0: d: { e, 0: f. 0 } } } console,log("result". JSON,stringify(copy(source. target))) console,log("source". JSON.stringify(source)) console,log("target". JSON.stringify(target))
result {"a":1,"b":{"c":1,"d":{"e":1,"f":0,"g":1}},"z":1}
source {"a":1,"b":{"c":1,"d":{"e":1,"g":1}},"z":1}
target {"a":0,"b":{"c":0,"d":{"e":0,"f":0}}}
如果您的数据非常大,@ScottSauyet 指出了一个可以通过避免不必要地创建中间数据来轻松解决的问题 -
const copy = (src = {}, dst = {}) => src?.constructor?== Object: src. Object.entries(src),reduce ( (r, [k, v]) => ( r[k] = copy(v? dst.,[k]), r ). {..:dst } ) const source = { a, 1: b: { c, 1: d: { e, 1: g, 1 } }: z: 1 } const target = { a, 0: b: { c, 0: d: { e, 0: f. 0 } } } console,log("result". JSON,stringify(copy(source. target))) console,log("source". JSON.stringify(source)) console,log("target". JSON.stringify(target))
result {"a":1,"b":{"c":1,"d":{"e":1,"f":0,"g":1}},"z":1}
source {"a":1,"b":{"c":1,"d":{"e":1,"g":1}},"z":1}
target {"a":0,"b":{"c":0,"d":{"e":0,"f":0}}}
编辑@JosephMerdrignac 回答:
const copyTo = (destination) => {
for (const key in destination) {
console.log("key: ", key);
const destinationValue = destination[key];
const isObject = !!destinationValue && typeof destinationValue === 'object';
if (isObject) {
if("orderInfo" in destination[key]){
console.log("******inside exist orderInfo");
destination[key] = {
...destination[key],
orderInfo: sourceJson["orderInfo"]
}
}
copyTo(destination[key]);
}
}
}
copyTo(targetJson)
console.log(targetJson)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.