繁体   English   中英

想要将嵌套的for循环转换为递归,

[英]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 -

  1. 如果src不是 object,则返回未修改的src
  2. (归纳) 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM