How to transfer props of an object from one location to another?

前端 未结 4 1203
长情又很酷
长情又很酷 2020-12-20 09:39

Following is an object with some deep properties.

const InitialObj = {
    Store: {propsFromStore: {}},
    Market: {propsFromMarket: {}},
    GoDown: {prop         


        
相关标签:
4条回答
  • 2020-12-20 10:08

    You can create a function to check if the key is one of "Store", "Market" or "GoDown" and replace it with the corresponding value. If the value of the key is an object(typeof object) then recursively call the function and repeat.

    const obj = {
       Store: {
           propsFromStore: {}
       },
       Market: {
           propsFromMarket: {}
       },
       GoDown: {
           propsFromDown: {}
       }
    }
    const whiteList = ["Store", "Market", "GoDown"]
    
    const replacer = object => Object.fromEntries(Object
        .entries(object)
        .map(([key, value]) => 
            [key, value && typeof value === "object" ? replacer(value) : whiteList.includes(value) ? obj[value] : value ]
        )
    )
    var initialObj = {
        fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
        vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
        fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    }
    const finalObj = replacer(initialObj)
    console.log(finalObj) // desired output
    

    I hope it helps.

    0 讨论(0)
  • 2020-12-20 10:09

    You can use a first function which will find which props should serve as references (Store, Market, GoDown), and use recursion on the others, with an auxiliary function:

    const InitialObj = {
      Store: {propsFromStore: {}},
      Market: {propsFromMarket: {}},
      GoDown: {propsFromDown: {}},
      fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
      vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
      fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
    };
    
    function hydrateObj(obj, keys) {
      const refs = keys.reduce((o, k) => ({...o, [k]: obj[k]}), {});
      return Object.entries(obj).reduce((res, [k, v]) => {
        if(!keys.includes(k)) {
          res[k] = hydrateObjAux(v, keys, refs);
        }
        return res;
      }, {});
    }
    
    function hydrateObjAux(obj, keys, refs) {
      return Object.entries(obj).reduce((res, [k, v]) => {
        if(keys.includes(v)) {
          res[k] = refs[v];
        } else {
          res[k] = hydrateObjAux(v, keys, refs);
        }
        return res;
      }, {});
    }
    
    const res = hydrateObj(InitialObj, ['Store', 'Market', 'GoDown']);
    document.body.innerHTML = '<pre>' + JSON.stringify(res, 0, 4) + '</pre>';

    0 讨论(0)
  • 2020-12-20 10:16

    Based on your comments that you separate replacement object from InitialObj by capitalised first letter.

    • Separate replacementObject from InitialObj
    • Recursively replace key string based on replacementObject Note: I don't know what type you have, so I set any for every type. It better to define and set correct type if you'r using ts.

    const InitialObj: any = {
        Store: {propsFromStore: {}},
        Market: {propsFromMarket: {}},
        GoDown: {propsFromDown: {}},
        fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
        vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
        fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
      }
      
      const replacementDict: any ={}
      
      // take Store, Market, GoDown from InitialObj to replacementDict
      Object.keys(InitialObj).forEach(key =>{
        // Check if the first letter is capitalised or not
        if(key[0].match(/^[A-Z]$/)){
          replacementDict[key] = InitialObj[key]
          delete InitialObj[key]
        }
      })
      
      
      function converter(obj: any){
        if(typeof obj !== "object") return
      
        Object.entries(obj).forEach(([key, value]: [any, any]) => {
          if(replacementDict[value]){
            obj[key] = replacementDict[value]
          }
          if(typeof obj[key] === "object"){
            converter(obj[key])
          }
        })
      }
      
      converter(InitialObj)
      console.log(InitialObj)

    0 讨论(0)
  • 2020-12-20 10:18

    The obvious solution would be to simply recursively iterate over all object properties, however it might be unnecessarily complicated and time consuming for such a simple case. Assuming we want to replace all instances of values being strings like "Store" and so on, we could transform the object into a string and do a simple replace function on it's contents, turning it back into object afterwards.

    const obj = {
        Store: {propsFromStore: {}},
        Market: {propsFromMarket: {}},
        GoDown: {propsFromDown: {}},
        fruits: {store_c: "Store", otherProp1: {store_e: "Store", otherSubProp1: {}}, otherProp2: {}},
        vegetables: {market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown", }}},
        fancy:{store_t: "Store", market_d: "Market", otherProp1: {otherSubProp1: {godown_r: "GoDown" }}}
    }
    
    
    // please note the existence of ":" in front of the searched term which ensures the replaced value is actually a value not a key of the nested objects
    const replaced = JSON.parse(JSON.stringify(obj)
      .replace(/:"Store"/g, ": {\"propsFromStore\": {}}")
      .replace(/:"Market"/g, ": {\"propsFromMarket\": {}}")
      .replace(/:"GoDown"/g, ": {\"propsFromDown\": {}}"))
    
    console.log(replaced)

    Of course this solution would not work if the properties of your objects are more complicated / require their own custom serialization method. An example of such a situation:

    const obj = { x: [10, undefined, null] }
    
    console.log(JSON.stringify(obj)); // logs `{"x":[10,null,null]}` effectively losing distinction between undefined and null
    
    const replaced = JSON.stringify(obj, (k, val) => typeof val === "undefined" ? "undefined" : val );
    console.log(replaced) // with custom replacer can keep information that would otherwise be lost
    
    const rereplaced = JSON.parse(replaced, (k, val) => val === "undefined" ? undefined : val)
    console.log(rereplaced) // gets it's undefined value back

    0 讨论(0)
提交回复
热议问题